LitSoz 2.0: Einführung in die Plugin-Schnittstelle

Inhalt

1. Grundlagen
1.1 Procedure GETCOUNT
1.2 Procedure INIT
1.3 Procedure START
1.4 Procedure FREE
1.5. Callbacks
2. Plugin-Arten
2.1 Standard-Plugins
2.2 Literaturbaum-Plugins
2.3 Import-Plugins
2.4 Export-Plugins

 
 
 
 


1. Grundlagen

Jedes LitSoz 2.0-Plugin ist im Grunde eine Windows-DLL (in LitSoz ind *.plg umbenannt), die bestimmte Routinen zur Verfügung stellt. Jede DLL kann dabei mehrere unabhängige Plugins enthalten. Die DLLs exportieren eine Reihe von Funktionen und Proceduren, über die LitSoz auf die Plugins zugreifen kann. Dies ist zum einen die Funktion getcount, die als Rückgabewert die Anzahl der Plugins pro DLL hat.

Jedes Plugin in einer PLG-Datei besteht aus drei Proceduren mit den Namen INITx, STARTx und FREEx. das x steht dabei für eine fortlaufende Nummer von 0 ab. Mit der Procedure INITx wird das Plugin initialisiert. Es kann hier z.B. Speicher reservieren und hohlt sich Zeiger auf Funktionen in der LitSoz EXE-Datei, um auf LitSoz zugreifen zu können. Außerdem gibt es Informationen über sich selbst (Name ...) an LitSoz zurück. Mit STARTx wird das Plugin gestartet. In der Procedure FREEx wird es 'deinitialisiert' und kann z.B. Speicher wieder freigeben.

Eine Plugin-DLL könnte z.B. forlgenden Aufbau haben:
 
 

library plugin;

uses
  SysUtils,
  Classes,
  windows,
  Messages,
  Controls,
  Dialogs,
  PluginDef;  // PluginDef definiert benötigte Typen usw. für Plugins

{$E plg}

{$R *.RES}

// Plugin 0: Initialisierung & registrieren
procedure INIT0(getProcAdress:TFarProc; var name, copyright, buttonname, buttonpicpath, menupicpath:PChar; var startoption:byte); export;
begin
  // ...
end;

// Plugin 0: Ausführen
procedure START0; export;
begin
  // ...
end;

// Plugin 0: Speicher freigeben
procedure FREE0; export;
begin
  // ...
end;
 

// Plugin 1: Initialisierung & registrieren
procedure INIT1(getProcAdress:TFarProc; var name, copyright, buttonname, buttonpicpath, menupicpath:PChar; var startoption:byte); export;
begin
  // ...
end;

// Plugin 1: Ausführen
procedure START1; export;
begin
  // ...
end;

// Plugin 1: Speicher freigeben
procedure FREE1; export;
begin
  // ...
end;
 
 

// GETCOUTN gibt die Anzahl der Plugins in der DLL zurück
function GETCOUNT:longint; export;
begin
  result:=2;
end;

exports GETCOUNT,
        INIT0, START0, FREE0,         // Plugin 0
      INIT1, START1, FREE1;        // Plugin 1
begin
end.
 

Das obige Beispiel kann man auch als Rumpf für eigene Plugins verwenden.

Wenn Strings zwischen Plugin und EXE ausgetaucht werden sollen geschieht dies ausschließlich als nullterminierte PCHAR-Strings!
 


1.1 Procedure GETCOUNT

Man sieht am obigen Beispiel das die Procedure GETCOUNT nur aus einer Zeile besteht. Sie dient ja auch nur dazu die Anzahl der Plugins in der DLL zurückzugeben.


1.2 Procedure INIT

 
procedure INITx(getProcAdress:TFarProc; var name, copyright, buttonname, buttonpicpath, menupicpath:PChar; var startoption:byte);

Diese Procedure hat drei Funktionen.

Zum einen übergibt das Plugin mit ihr Informationen über sich selbst an LitSoz. Dies geschieht mit folgenden Variaben:

 
Variablenname Funktion
name Rückgabe des namens des Plugins an LitSoz
copyright Rückgabe von Copyright-Informationen an LitSoz
buttonname Bezeichnung für das Plugin, die auf Schaltflächen und in Menüs angezeigt werden soll
buttonpicpath Der Name einer Ressource in der Plugin-DLL, die als Bildchen auf Buttons erscheinen soll. Bei der Resource muss es sich um ein max. 32*32 Pixel großes Bitmap handeln.
menupicpath Der Name einer Ressource in der Plugin-DLL, die als Bildchen in Menüs erscheinen soll. Bei der Resource muss es sich um ein 16*16 Pixel großes Bitmap handeln (Größe unbedingt beibehalten !!!).
startoption Angabe, wie/wo das Plugin in LitSoz eingebunden werden soll. Folgende Konstanten sind in PluginDef.pas hierfür vorgesehen:

soDefault:Byte=0; // Start nach Voreinstellung (auf Click hin, soMenu)
soProgStart:Byte=1; // Start beim Programmstart
soProgClose:Byte=2; // Start beim schließen des Programmes
soMenu:Byte=3;    // Start auf Auswahl aus dem Plugin-Menü/Button
soImport:Byte=4// Import-Plugin
soExport:Byte=5// Export-Plugin
soTreeView:Byte=6; // Plugin für Literaturbaum
soEditPopUp:Byte=7; // Start durch Klick auf Eintrag im Popup-Menü
soMenuDataset:Byte=8; // Start durch Klick auf Eintrag im datensatz-Menü
soMenuAdmin:Byte=9; // Start durch Klick auf Eintrag im Admin-Menü
soMenuAdminDB:Byte=10; // Start durch Klick auf Eintrag im Admin|Datenbank-Menü
soMenuSelection:Byte=11; // Start durch Klick auf Eintrag im Auswahl-Menü
soMenuDatabase:Byte=12; // Start durch Klick auf Eintrag im Datenbank-Menü
soMenuFile:Byte=13; // Start durch Klick auf Eintrag im Datei-Menü
soMenuView:Byte=14; // Start durch Klick auf Eintrag im Ansicht-Menü
soMenuHelp:Byte=15; // Start durch Klick auf Eintrag im Hilfe-Menü
soMenuDatasetFromCurrentDataset:Byte=16; // Start durch Klick auf Eintrag im Datensatz|Aus aktuellem Datensatz-Menü
soMenuDatabaseMoreSearch:Byte=17; // Start durch Klick auf Eintrag im Datenbank|weitere Suchvorgänge-Menü
soMenuDESL:Byte=18; // Start durch Klick auf Eintrag im Datenbank|Literaturangabe-Menü (bzw. Button)

Zum zweiten erhält es mit getProcAdress einen Pointer auf eine Procedure in der LitSoz-EXE, über die es Pointer auf weitere Procedure in dieser EXE abrufen kann. Dies ermöglicht den Zugriff auf LitSoz vom Plugin aus. Die Procedure getProcAdress hat folgenden Typ:
tHostGetProcAdress  = function(id:word):TFarProc;
aus PluginDef.pas

Der Parameter id gibt an, welche auf welche procedure in der LitSoz-EXE ein Pointer zurückgegeben werden soll. Für id sind in der Unit PluginDef.pas Konstanten und Typen definiert. Die abrufbaren Proceduren werden hier beschrieben. Es ist sinnvoll für jede Procedure eine globale Variable anzulegen, auf die alle Routinen in der DLL zugreifen können. Jedes Plugin würde dann in der START-Procedure die globalen Variablen setzen, die es braucht und später darauf zugreifen. Die erhaltenen Pointer bleiben während der gesammten Ausführungszeit des Plugins gültig. Folgende Zeichnung verdeutlicht das Konzept:






Die dritte Funktion ist, das dem Plugin hier die gelegenheit gegeben wird Speicher zu belegen, der später in der FREE-Procedure wieder freigegeben wird. So muss er nicht bei jedem Aufruf des Plugins neu belegt und freigegeben werden.
 
 
 


1.3 Procedure START

procedure STARTx;
Diese Procedure wird aufgerufen, wenn das Plugin aufgerufen wird. Sie enthält den eigentlichen Funktionscode des Plugins. je nach Art des Plugins stehen hier verschiedene Dinge. Für einige Typen von plugins muss der Code spezielle Vorraussetzungen erfüllen. Hierzu zählen Spezialplugins, wie Import- und Export-Plugins, sowie Plugins für Literaturbäume.


1.4 Procedure FREE

 
procedure FREEx;

Diese Procedure dient eigentlich nur dazu speicher den das Plugin belegt hat frei zugeben.


 


1.5 Callbacks

Callbacks ermöglichen es einem Plugin der LitSoz-EXE mitzuteilen, dass bestimmte Procedure (Callback-Proceduren) zu bestimmten Ereignissen aufgerufen werden sollen. So ist es möglich, dass ein Plugin auf Ereignisse im Programmablauf (z.B. neuer Datensatz ...) reagiert. Außerdem werden Callbacks von Export-Plugins standardmäßig eingesetzt.

Um allgemein Callbacks bei LitSoz zu registrieren muss die Schnittstellenroutine
 

function PluginRegisterCallback(callback: TFarProc; startoption: byte):longint;

aufgerufen werden. Ihr übergibt man als callback einen Pointer auf die Callback-Procedure (diese muss ebenfalls exportiert werden!). Zusätzlich gibt man in startoption das Ereignis an, zu dem callback aufgerufen wird. Für startoption sind folgende Konstanten in PluginDef.pas definiert:

pcbAfterScroll=1;    // Aufruf, nachdem zu einem neuen Datensatz gewechselt wurde
pcbAfterCancel=2;    // Aufruf, nachdem Eingaben verworfen wurden
pcbAfterClose=3;     // Aufruf, nachdem eine Datenbank geschlossen wurde
pcbAfterDelete=4;    // Aufruf, nachdem ein Datensatz gelöscht wurde
pcbAfterEdit=5;      // Aufruf, nachdem ein Datensatz in den Editiermodus übergegangen ist
pcbAfterInsert=6;    // Aufruf, nachdem ein Datensatz hinzugefügt wurde
pcbAfterOpen=7;      // Aufruf, nachdem eine Datenbank geöffnet wurde
pcbAfterPost=8;      // Aufruf, nachdem eine Änderung übernommen wurde
pcbAfterRefresh=9;   // Aufruf, nachdem Daten neu gelesen wurden (Refresh)
pcbBeforeCancel=10// Aufruf, bevor Eingaben verworfen wurden
pcbBeforeClose=11;   // Aufruf, bevor eine Datenbank geschlossen wurde
pcbBeforeDelete=12// Aufruf, bevor ein Datensatz gelöscht wurde
pcbBeforeEdit=13;    // Aufruf, bevor ein Datensatz in den Editiermodus übergegangen ist
pcbBeforeInsert=14// Aufruf, bevor ein Datensatz hinzugefügt wurde
pcbBeforeOpen=15;    // Aufruf, bevor eine Datenbank geöffnet wurde
pcbBeforePost=16;    // Aufruf, bevor eine Änderung übernommen wurde
pcbBeforeRefresh=17; // Aufruf, bevor Daten neu gelesen wurden (Refresh)
pcbBeforeScroll=18// Aufruf, bevor zu einem neuen Datensatz gewechselt wurde


Callback-Procedure müssen folgenden typ haben, um gültig zu sein:
 

tPluginCallbackProc = procedure(data1, data2, data3, data4, data5:Pointer);

In data1 bis data5 können Informationen an das Plugin übergeben werden. Dies hängt aber vom Ereignis ab und ist momentan für zukünftige Erweiterungen vorgesehen. In der aktuellen LitSoz-Version wird an alle Callbacks für jeden datax-Wert nil übergeben!
 

Folgendes Beispiel zeigt, wie ein Callback in ein Plugin eingebaut werden könnte:
 

library plugin;

uses
  SysUtils,
  Classes,
  windows,
  Messages,
  Controls,
  Dialogs,
  PluginDef;  // PluginDef definiert benötigte Typen usw. für Plugins

{$E plg}

{$R *.RES}

var 
  getProcA: tHostGetProcAdress;
  RegisterPlugin: tPluginRegisterCallback;
 

// Plugin 0: Callback-Procedure, Aufruf wenn datensatz eingefügt wurde
procedure CALLBACK(data1, data2, data3, data4, data5:Pointer); export;
begin
  ShowMessage('Ein neuer Datensatz wurde eingefügt. Geben Sie nun alle Daten ein!');
end;

// Plugin 0: Initialisierung & registrieren
procedure INIT0(getProcAdress:TFarProc; var name, copyright, buttonname, buttonpicpath, menupicpath:PChar; var startoption:byte); export;
begin
  Name:=PChar('Callback-Test-Plugin');           // Rückgabe des Plugin-Namens
  Copyright:=PChar('(c) 2001 by Jan W. Krieger'); // Rückgabe von Copyright-Informationen
  buttonpicpath:=PChar('');              // Rückgabe des großen Bildchens
  menupicpath:=PChar('');              // Rückgabe des kleinen Bildschens
  buttonname:=PChar('Callback-Test');            // Rückgabe der menü-Beschriftung

  // Start beim Programmstart von LitSoz: kein Menüeintrag, das diese nicht nötig
  startoption:=soProgStart

    // Funktionspointer auf Procedure in der EXE holen.
  @getProcA := getProcAdress;
  @RegisterPlugin := getProcA(gpPluginRegisterCallback);

    // Plugin registrieren, Ereignis: nach Einfügen eines Datensatzes
  registerPlugin(CALLBACK, pcbAfterInsert);
end;

// Plugin 0: Ausführen
procedure START0; export;
begin
  // hier passiert nichts
end;

// Plugin 0: Speicher freigeben
procedure FREE0; export;
begin
  // hier passiert ebenfalls nichts
end;
 

// GETCOUTN gibt die Anzahl der Plugins in der DLL zurück
function GETCOUNT:longint; export;
begin
  result:=1;
end;

exports GETCOUNT,
        INIT0, START0, FREE0,         // Plugin 0
       CALLBACK;                     //Callback-Procedure

begin
end.
 

Quellcode: examplesource/plug_exmpl1.dpr -- Delphi 5 Quellcode [1,86 kB]


2. Plugin-Arten

Es gibt in LitSoz vier grundlegend verschiedene Arten von Plugins. Ihnen ist allen gemeinsam, dass sie die gleichen Proceduren implementieren müssen. Sie unterscheiden sich aber grundlegend im Quellcode in der START-Procedure.
 
 


2.1 Standard-Plugins

Standard-Plugins können ganz unterschiedliche Funktionen haben. Sie können etwa Felder automatisch füllen, oder zusätzliche Funktionen, wie die Überwachung der BDE realisieren. Beim Aufruf des Plugins wird dann z.B. ein Dialog mit allen informationen angezeigt. Sie könnten aber auch die Daten der Datenbank auswerten oder weiterverarbeiten.

Bei ihrer Implementation müssen keine Besonderheiten beachtet werden. Der Code steht in der START-Procedure. Wie ein Standard-Plugin aufgerufen wird wird durch seine Startoption in der INIT-Procedure festgelegt. Folgende Konstanten für startoption erzeugen Standard-Plugins:

soDefault, soProgStart, soProgClose, soMenu:Byte, soEditPopUp, soMenuDataset, soMenuAdmin, soMenuAdminDB, soMenuSelection, soMenuDatabase, soMenuFile, soMenuView, soMenuHelp, soMenuDatasetFromCurrentDataset, soMenuDatabaseMoreSearch, soMenuDESL
Die Bedeutung der Konstanten wird unter 1.2 INIT-Procedure beschrieben.


2.2 Literaturbaum-Plugins

Literaturbaum-Plugins dienen dazu, spezielle Literaturbäume zu erzeugen. dazu greifen sie auf die daten der aktuellen LitSoz-datenbank zu und erzeugen eine LB-Datei, die danach von LitSoz geladen wird.

In der INIT-Procedure muss ein Literaturbaum-Plugin mit der Startoption soTreeView registriert werden. Es wird dann auf der Bildschirmseite "Baumansicht" im Menü der Schaltfläche "autom. Literaturbäume" angezeigt.

In der START-Procedure wird zuerst die LB-Datei erzeugt und auf Festplatte gespeichert. Danach wird die LitSoz-Routine TreeViewLoadFromFile mit dem Dateinamen der LB-Datei als Parameter aufgerufen. Dies lädt die LB-Datei in den Literaturbaum in LitSoz. Danach kann die Datei gelöscht werden. Als Beispiel soll hier ein Ausschnitt aus den Standard-Plugins (stndplugins.plg) dienen: Beispiel zu LB-Plugins.


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


erstellt/bearbeitet: 25. August 2001     --  © 2001 by Jan W. Krieger ( jan@jkrieger.de)