Haben Sie jemals Adobe Photoshop verwendet? Für Laien sind Plugins nur Codeblöcke, die der Anwendung von außen (z. B. in einer DLL) zur Verfügung gestellt wurden. Der Unterschied zwischen einem Plugin und einer normalen DLL besteht darin, dass das Plugin die Funktionalität der übergeordneten Anwendung erweitern kann. Beispielsweise hat Photoshop selbst keine große Menge an Bildverarbeitungsfunktionen. Die Zugabe von Plug-Ins verleiht ihm einen großartigen Effekt wie Unschärfe, Fleck und alle anderen Stile, und keiner von ihnen hat die übergeordnete Anwendung selbst.
Dies ist sehr gut für Bildverarbeitungsprogramme, aber warum müssen Sie viele Anstrengungen aufwenden, um kommerzielle Anwendungen zu vervollständigen, die Plugins unterstützen? Nehmen wir an, geben wir ein Beispiel an, dass Ihre Bewerbung einige Berichte generiert. Ihre Kunden werden auf jeden Fall weiter nach Updates fragen oder neue Berichte hinzufügen. Sie können einen externen Berichtsgenerator wie Report Smith, eine nicht so sehr ähnliche Lösung, verwenden, erfordert die Veröffentlichung zusätzlicher Dateien, zusätzliches Training für Benutzer usw. Sie können auch QuickReport verwenden, aber dies wird Sie in einen Alptraum für die Versionskontrolle versetzen - wenn Sie Ihre Bewerbung jedes Mal wieder aufbauen möchten, wenn Sie die Schriftart ändern.
Solange Sie den Bericht im Plugin erstellen, können Sie ihn verwenden. Benötigen Sie einen neuen Bericht? Kein Problem, installieren Sie einfach eine DLL und Sie werden sie beim nächsten Start der Anwendung sehen. Ein weiteres Beispiel ist eine Anwendung, die Daten von externen Geräten (z. B. Barcode -Scanner) verarbeitet. Durch das Schreiben der Verarbeitungsroutine für Geräteschnittstellen als Plug-In können Sie maximale Skalierbarkeit erzielen, ohne Änderungen an der übergeordneten Anwendung vorzunehmen.
Erste Schritte
Das Wichtigste, bevor Sie mit dem Schreiben von Code beginnen, ist, herauszufinden, welche Funktionen Ihre Anwendung verlängern muss. Dies liegt daran, dass das Plugin über eine bestimmte Schnittstelle mit der übergeordneten Anwendung interagiert, die entsprechend Ihren Anforderungen definiert wird. In diesem Artikel werden wir 3 Plugins erstellen, um verschiedene Möglichkeiten zu präsentieren, wie das Plugin mit der übergeordneten Anwendung interagiert.
Wir werden das Plugin in eine DLL machen. Bevor wir dies tun, müssen wir jedoch eine Shell machen, um sie zu laden und zu testen. Abbildung 1 zeigt das Testprogramm, nachdem das erste Plug-In geladen wurde. Das erste Plugin erreicht nichts Großes und tatsächlich ist es nur eine Zeichenfolge zurückzugeben, die sich selbst beschreibt. Es bestätigt jedoch einen wichtigen Punkt-es funktioniert ordnungsgemäß mit oder ohne Plug-in-Anwendungen. Wenn es kein Plug-In gibt, wird es in der Liste der installierten Plug-Ins nicht angezeigt, aber die Anwendung kann trotzdem Funktionen normal ausführen.
Der einzige Unterschied zwischen unserer Plug-in-Shell und normalen Anwendungen ist die Sharemem-Einheit in der Projektquelldatei, die in der Verwendungsklausel angezeigt wird, und der Code, der die Plug-in-Datei lädt. Gibt es eine Anwendung, die die String -Parameter zwischen sich und der untergeordneten DLL übergibt? Um diese Shell zu testen, müssen Sie die Datei delphimm.dll aus dem Delphi/Bin -Verzeichnis auf den Pfad kopieren, der in der Pfadumgebungsvariable oder im Verzeichnis, in dem sich die Anwendung befindet, enthalten ist. Die Datei muss auch gleichzeitig verteilt werden, wenn die endgültige Version veröffentlicht wird.
Das Plug-In wird in dieser Testhülle über den LoadPlugins-Prozess geladen, der im Formungs-Ereignis im Hauptfenster aufgerufen wird, siehe Abbildung 2. Dieser Prozess verwendet FindFirst- und FindNext -Funktionen, um Plugin -Dateien im Verzeichnis zu finden, in dem sich die Anwendung befindet. Verwenden Sie nach dem Finden einer Datei den in Abbildung 3 gezeigten LoadPlugins -Prozess, um sie zu laden.
{Suchen Sie Plugin -Dateien im Anwendungsverzeichnis}
Prozedur tfrmmain.loadplugins;
var
SR: Tsearchrec;
Pfad: String;
Gefunden: Ganzzahl;
Beginnen
Pfad: = extractFilepath (application.exename);
versuchen
Gefunden: = findFirst (Pfad + cplugin_mask, 0, sr);
während gefunden = 0 beginnt
LoadPlugin (SR);
Gefunden: = findNext (SR);
Ende;
Endlich
FindClose (SR);
Ende;
Ende;
{Laden Sie die angegebene Plugin -DLL.
procedure tfrmmain.loadplugin (SR: tSearchrec);
var
Beschreibung: String;
Libhandle: Ganzzahl;
Beschreibung: tplugindeScribe;
Beginnen
LibHandle: = loadlibrary (pchar (sr.name));
Wenn libhandle $#@60; $#@62;
Beginnen
Beschreibung: = getProcaddress (libHandle, cplugin_describe);
Wenn zugewiesen (beschreiben) dann
BeschreibungProc (Beschreibung);
memplugins.lines.add (Beschreibung);
Ende
anders
Beginnen
Messagedlg ('Datei' ' + sr.name +' "ist kein gültiges Plug-In.
Mtinformation, [Mbok], 0);
Ende;
Ende
anders
Messagedlg ('Es ist ein Fehler beim Laden des Plug-Ins "' + ist aufgetreten
sr.name + '".', mterror, [mbok], 0);
Ende;
Die Lastplugin-Methode zeigt den Kern des Plug-in-Mechanismus. Zunächst ist das Plugin als DLL geschrieben. Zweitens wird es dynamisch durch die Lastlibrary -API geladen. Sobald die DLL geladen ist, benötigen wir einen Weg, um auf die von ihr enthaltenden Prozeduren und Funktionen zugreifen zu können. API -Aufrufe GetProcaddress liefern diesen Mechanismus, der einen Zeiger auf die erforderliche Routine zurückgibt. In unserer einfachen Demonstration enthält das Plugin nur eine Prozedur namens "Beschreibung", die durch die konstante cplugin_describe angegeben ist (der Fall des Verfahrensnamens ist sehr wichtig, und der Name, der zum GetProcaddress übergeben wird, muss genau dem in der DLL enthaltenen Routinamen enthalten sein. . Wenn in der DLL keine angeforderte Routine gefunden wird, gibt GetProcadDree NIL zurück, sodass Sie die zugewiesene Funktion verwenden können, um den Rückgabewert zu bestimmen.
Um Zeiger auf eine benutzerfreundliche Weise auf eine Funktion zu speichern, ist es erforderlich, einen bestimmten Typ für die verwendeten Variablen zu erstellen. Beachten Sie, dass der Rückgabewert von GetProcaddress in einer Variablen, Beschreibung, zum TPLUGInDescribe -Typ gespeichert ist. Hier ist seine Aussage:
Typ
TPlugInDescribe = procedure (var desc: string);
Da das Verfahren innerhalb der DLL vorhanden ist, werden alle Exportroutinen durch Standard -Call -Conversions zusammengestellt, sodass die STDCall -Anzeige erforderlich ist. Dieser Vorgang verwendet einen VAR -Parameter, der die Plugin -Beschreibung enthält, wenn der Prozess zurückgibt.
Um den gerade erhaltenen Prozess aufzurufen, verwenden Sie einfach die Variable, die die Adresse als Prozessname speichert, gefolgt von Parametern. In unserem Fall die Erklärung:
BeschreibungProc (Beschreibung)
Der im Plug-In erhaltene Beschreibungsprozess wird aufgerufen und die Beschreibungsvariable wird mit einer Zeichenfolge besiedelt, die die Funktionalität des Plug-in beschreibt.
Konstruktions-Plug-In
Wir haben die übergeordnete Anwendung erstellt und es ist Zeit, das Plugin zu erstellen, das wir laden möchten. Die Plugin -Datei ist eine Standard -DLL -DLL. Wir erstellen daher ein neues DLL -Projekt aus der Delphi -IDE und speichern es. Da die exportierte Plug-in-Funktion die String-Parameter verwendet, sollte die Sharemen-Einheit zuerst in der Verwendung des Projekts verwendet werden. In Abbildung 4 werden die Projektquelldatei unseres einfachen Plug-Ins aufgeführt.
Verwendung
Sharemem, Sysutils, Klassen,
Haupt in 'main.pas';
{$ E plg.}
Exporte
Beschreibung;
Beginnen
Ende.
Obwohl das Plugin eine DLL -Datei ist, müssen es keine .dll -Erweiterung geben. Ein Grund reicht aus, um uns einen Grund zu geben, die Erweiterung zu ändern: Wenn die übergeordnete Anwendung nach dem Laden der Datei sucht, kann die neue Erweiterung als bestimmte Dateimaske dienen. Durch die Verwendung einer anderen Erweiterung (unser Beispiel verwendet *.plg) können Sie etwas sicher sein, dass die Anwendung die entsprechenden Dateien nur lädt. Compile Indicator $ x kann diese Änderung erreichen, oder Sie können die Erweiterung über die Anwendungsseite des Dialogfelds Projektoptionen festlegen.
Der Code für das erste Beispiel -Plugin ist sehr einfach. Abbildung 5 zeigt den Code in einer neuen Einheit. Beachten Sie, dass der Beschreibungsprototyp mit dem TplugIndescribe -Typ in der Shell -Anwendung übereinstimmt und das zusätzliche reservierte Export -Wort verwendet, um anzugeben, dass der Prozess exportiert wird. Der exportierte Prozessname wird auch im Abschnitt Exporte des Hauptprojektquellcodes angezeigt (aufgeführt in Abbildung 4).
Einheit Main;
Schnittstelle
Prozedurbeschreibung (var Desc: String);
Export;
Durchführung
Prozedurbeschreibung (var Desc: String);
Beginnen
Desc: = 'Test Plugin v1.00';
Ende;
Ende.
Kopieren Sie es vor dem Testen dieses Plugins in den Pfad der Hauptanwendung. Am einfachsten ist es, im Unterverzeichnis des Heimverzeichnisses ein Plug-In zu erstellen und dann den Ausgangspfad auf den Hauptpfad zu setzen (die Verzeichnisse/Bedingungen des Dialogfelds für Projektoptionen können auch für diese Einstellung verwendet werden).
debuggen
Lassen Sie mich nun ein besseres Feature in Delphi 3 vorstellen: die Fähigkeit, DLLs aus der IDE zu debuggen. In einem DLL -Projekt können Sie ein Programm als Host -Anwendung über das Dialogfeld "Ausführen" angeben. Anschließend können Sie Haltepunkte in Ihrem DLL -Code einstellen und F9 drücken, um ihn auszuführen - genau wie Sie es in einer normalen Anwendung tun würden. Delphi wird das angegebene Host -Programm ausführen und die DLL mit Debug -Informationen zusammenstellen, leiten Sie im DLL -Code zum Haltepunkt.