Appendiks B. Lav yderligere plugin

Indholdsfortegnelse

Lav et basalt plugin
XML-filen
Den delte objektfil
Kompilér pluginnet
Lav et plugin for lineærindstilling
Deklarationsfiler
Implementér nødvendige funktioner
Kalde tilpasningfunktionerne
Eksempel
Lav plugin for ikke-lineær indstilling
Deklarationsfiler og definitioner
Implementér nødvendige funktioner
Kalde tilpasningfunktionerne
Eksempel
Lav plugin for passfilter
Deklarationsfiler
Nødvendige funktioner
Kald filterfunktionen
Eksempel

Kst har en enkel og standardiseret grænseflade som tillader nemt at lave oprette yderligere plugin. Udover at give detaljer om grundlæggende krav for plugin, beskriver følgende afsnit hvordan færdigskrevne deklarationsfiler kan bruges til at lave visse slags plugin.

Lav et basalt plugin

Et Kst-plugin består af to filer: en XML-fil og en delt objektfil.

XML-filen

XML-filen sørger for information om plugin og beskriver dets inddata og uddata. Det følgende er et eksempel på en XML-fil for et Kst-plugin:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Module SYSTEM "file:/Repository/Level2/Soft/ProC/moduledef.dtd">

<module>

<intro>
<moduletame name="testplugin"/>    <!-- Modulets navn -->
<author name="Rick Chern"/> <!-- Forfatterens navn -->
<description text="Et testplugin for mig"/> <!-- En beskrivelse af modulet -->
<version minor="1" major="0"/>  <!-- Modulets versionsnummer -->
<state devstate="release"/>     <!-- Udviklingstilstanden for modulet (valgfrit)-->
</intro>

<interface>

<!--inputs here-->
<input>
<table type="float" name="Input Vector 1" descr="Den første inddatavektor" />
</input>

<input>
<float name="Input Scalar 1" descr="Den første inddataskalar" />
</input>

<!--outputs here-->
<output>
<table type="float" name="Output Vector 1" descr="Den første uddatavektor" />
</output>

<output>
<float name="Output Scalar 1" descr="Den første uddataskalar" />
</output>

</interface>

</module>

I almindelighed kan du bruge eksemplet ovenfor som en skabelon og ændre dele af det til at passe med dine behov. Som det ses i eksemplet, består XML-filen af knuden module. Knuden module indeholder knuderne intro og interface. Du skal ændre knuden intro på passende måde ved at bruge kommentarerne i XML-filen ovenfor som guider. Det er vigtigt at moduletame har egenskaben name sat til det samme navn som din delte objektfil vil bruge.

Knuden interface beskriver pluginnets egentlige inddata og uddata. Hver inddataværdi beskrives af knuden input, og hver uddataværdi beskrives af knuden output. Hver inddataværdi eller uddataværdi skal enten have delknuden table eller float. Egenskaben type i en table skal være sat til "float". Bemærk at rækkefølgen for inddata og uddata spiller en rolle: Rækkefølgen bruges til at afgøre indelsværdien for hver inddataværdi og uddataværdi i objektfilen, og er samme rækkefølge som de inddatafelter og uddatafelter der burges til at vise grænsefladen for plugin i Kst.

Når du er klar med XML-filen, gemmes den som [modulnavn].xml, hvor [modulnavn] er værdien for egenskaben name i knuden moduletame.

Den delte objektfil

Den delte objektfil indeholder selve pluginnets funktion. Med andre ord afgør den hvordan uddata skal laves ud fra givne inddata. Følgende krav gælder for den delte objektfil:

  • Objektet skal eksportere følgende C-link-symboler:

    int symbol(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[])

    hvor symbol skal være værdien på egenskaben name i knuden moduletame i XML-filen. Dette er den eneste funktion som vil blive kaldet af Kst (selv om du kan have flere funktioner). Det følgende beskriver hvert argument for funktionen:

    const double *const inArrays[]

    Feltet med inddatafelt. Hvert inddatafelt svarer til en inddatavektor. Felterne er i samme rækkefølge som vektorerne på listen i XML-filen, så inArrays[0] er feltet som representerer den første inddatavektor, inArrays[1] er feltet som representerer den andre inddatavektor, og så videre.

    const int inArraysLens[]

    Feltet som indeholder feltlængderne for hvert inddatafelt. Længderne opbevares i samme rækkefølge som felterne i inArrays[] (f.eks. er inArrayLens[0] længden på inArrays[0]).

    const double inScalars[]

    Feltet med inddataskalarer. Skalarerne opbevares i samme rækkefølge som de er på listen i XML-filen.

    double *outArrays[]

    Feltet med uddatafelt. Hvert uddatafelt svarer til en uddatavektor, og felterne skal være i samme rækkefølge som uddatavektorerne er på listen i XML-filen.

    int outArrayLens[]

    Feltet som skal indeholde længderne på uddatafelterne. Længderne skal opbevares i samme rækkefølge som i felterne i outArrays[].

    double outScalars[]

    Feltet med uddataskalarer. Skalarerne skal være i samme rækkefølge som de er på listen i XML-filen.

  • Funktionen skal returnere 0 hvis det lykkes at udføre den, og -1 ellers.

  • Koden i objektfilen skal håndtere uventede inddata, såsom tomme inddatafelter (i de fleste tilfælde er returværdien -1 tilstrækkelig når sådanne situationer opstår).

  • Antal og type af uddata skal være nøjagtigt som det angives i XML-filen.

  • Du skal formodentlig ændre størrelse på felterne i outArrays[]. For at gøre det, bruges funktionen realloc(). For eksempel

    outArrays[0]=(double*)realloc(outArrays[0], 5*sizeof(double));
    

    allokerer plads til fem dobbelte decimaltal i outArrays[0]. Brug ikke anden hukommelsesallokering end realloc().

  • Inddataargumenterne skal forblive konstante. Konvertér dem ikke til ikke-konstante typer.

Følgende er et eksempel på den delte objektfils kildekode for et enkelt plugin:

#include <stdlib.h>

extern "C" int testplugin(const double *const inArrays[], const int inArrayLens[],
                const double is[],
                double *outArrays[], int outArrayLens[],
                double outScalars[]);

int testplugin(const double *const inArrays[], const int inArrayLens[],
                const double is[],
                double *outArrays[], int outArrayLens[],
                double outScalars[])

//Accept 1 vector and 1 scalar. Multiply all elements of the vector by the
//scalar, and output the resulting vector. Also output the original scalar.
{
        //Set the outputs
        outArrayLens[0]=inArrayLens[0];

        //resize the output arrays
        outArrays[0]=(double*)realloc(outArrays[0], inArrayLens[0]*sizeof(double));

        //multiply each element of the input vector
        //by the scalar
        for (int i=0; i<inArrayLens[0]; i++)
        {
                outArrays[0][i]=inArrays[0][i] * is[0];
        }

        //now set the output scalar
        outScalars[0]=is[0];

        return 0;
}

Kompilér pluginnet

Hvis du bruger gcc til at kompilere pluginnet, kompileres objektfilen blot:

cc -Wall -c -o myplugin.o myplugin.c -fPIC -DPIC

og derefter oprettes det delte bibliotek:

ld -o myplugin.so -shared myplugin.o

De resulterende filer *.so og *.xml skal placeres i samme mappe. Når du bruger plugin-håndteringen i Kst til at indlæse XML-filen, kigger den automatisk efter den delte objektfil i samme mappe.