AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Plugin-System Version 3

Plugin-System Version 3

Ein Thema von Henning der zweite · begonnen am 19. Jul 2009 · letzter Beitrag vom 15. Mai 2011
Antwort Antwort
Seite 3 von 3     123
Henning der zweite
Registriert seit: 10. Mär 2008
Hallo!

In diesem Thread stelle ich euch das

Plugin-System V. 3.1.0


vor, und ich muss sagen, dass es mir sehr viel Denkarbeit gekostet hat.
Und Denkarbeit ist schwierig - darum hat das Denken letztendlich mehrere Wochen gebraucht, das implementieren dann aber nur 2 Tage.

Crosspost bei Delphi-Treff
Crosspost bei Delphi-Forum

Ach ja: zwischendurch gab es auch das Plugin-System Version 2.
Bei dieser Version hat mir die Interface-Referenzzählung aber einen gewaltigen Strich durch die Rechnung gezogen, darum habe ich es verworfen.
Das Plugin-System Version 1 findet ihr bei Delphi-Treff, ich werde es aber hier nicht verlinken, da es veraltet ist und ich es nicht mehr unterstütze.

WICHTIG:
Bei Unklarheiten bitte sofort Fragen - egal wie dumm die Fragen sind!

Allgemeine Informationen
Entwickler: Henning Dieterichs
Lizenz: Dieses System kann frei verwendet werden, ich würde mich aber darüber freuen, wenn ich bei Benutzung von diesem Plugin-System namentlich erwähnt werde!
Getestete Umgebung: Windows XP, Delphi 7 (mit früheren Version nicht getestet!).
Benötigte Fremdkomponenten: Keine.

Download
Ganz kurz vorweg: Download gibts hier (mit 9 Demos).
Größe ca. 100 KiB.

Hier gibts das ganze mit bereits kompilierten DLLs und Exen.
Größe ca. 3,5 MiB.

Alle benötigten Dateien sind jeweils im Archiv enthalten

Wichtigste Features (Insider-Wissen)
  • Client <-> Host und Client <-> Client Datenaustausch möglich
  • Sprachunabhängig
  • Objekt-Export
  • Vererbung, Überschreibung exportierter Objekte
  • Klassen-Export, Klassen-Methoden
  • Flexible Plugin-Quelle durch Plugin-Packages (z.B. aus DLLs)

Was macht dieses Plugin-System?
Dieses Plugin-System ist dazu dar, ein Programm zu schreiben, welches nachher beliebig erweitert werden kann.
Dabei können vorhandene Module überschrieben, erweitert und verbessert werden, ohne das an ihnen etwas verändert werden muss.

Für wen ist dieses Plugin-System geeignet?
Im Grunde genommen für jeden, der es sich zutraut, sich mit den Interfaces von Delphi rumzuschlagen - der Einstieg ist sehr kompliziert, das Ergebnis dafür aber um so besser.
Dieses Plugin-System kann für kleinere Programme als auch für größere verwendet werden - auch wenn das System nicht ganz ausgenutzt wird.
Dadurch können fremde Programme durch andere Entwickler spielend leicht verbessert oder nach ihren Wünschen angepasst werden.
So kann es beispielsweise ein Plugin geben, welches einem Programm ein Tray-Icon hinzufügt - dabei spielt es letzendlich keine Rolle, um welches Programm es sich handelt, solange es mit dem Plugin-System ausgestattet ist.

Wie kann das funktionieren?
Ganz einfach - über Interfaces.
Die gesamte Kommunikation innerhalb des Plugin-Systems baut nur auf Interfaces auf, weshalb das gesamte System sogar Programmiersprachen-Unabhängig ist.

Allerdings besitzen die Interfaces von Delphi eine sehr unangenehme Eigenschaft: die Referenzzählung.
Warum die so blöd ist, kann
hier und hier nachgelesen werden.

Das Problem habe ich letztendlich mit Pointer auf Interfaces in den Griff bekommen - bei ihnen ignoriert Delphi die Referenzzählung.
Allerdings muss dazu einiges beachtet werden:
Die PInterfaces (Pointer auf Interfaces) dürfen nicht (bzw. wenn, dann nur, wenn man weiß, was man tut) dereferenziert werden.
Wenn ein PInterface in ein anderes gewandelt werden soll, kann die Klasse TIntf dazu benutzt werden - sie verwaltet das dann.

Aufbau des Plugin-Systems


Begriffe
Damit die Erklärung einfacher wird, habe ich mir einige Begriffe einfallen lassen, bzw. sie mit einer Bedeutung belegt:

Plugin: Das Plugin ist die kleinste Einheit: es stellt ein Objekt bzw. seine Klasse dar
Package:Ein Package ist eine Ansammlung von Plugins
Host: Der Host ist das Modul, das die Packages verwaltet.
Client: Der Client ist das Gegenstück und stellt ein Package dar, die Multiplizität zum Host beträgt N:1
Library: Der Host verwaltet alle Packages in einer gemeinsamen Library (= Bücherei)

Units
Das Plugin-System besteht hauptsächlich aus 4 Units:
plgHeader (die wichtigste Unit)
plgCore (enthält allgemeine Klasse)
plgLibrary (für den Host)
plgPackage (für den Client)

Client (als DLL)
- Erstellen eines Plugins

Erst ein Plugin enthält ausführbaren Code und ist somit das wichtigste Element in diesem System.

-- Festlegen des Interfaces
Zuerst muss das Interface festgelegt werden, welches das Plugin implementiert. Jedes Interface muss eine GUID besitzen.
Ein Plugin kann auch mehrere Interfaces implementieren.

Beispiel:
Delphi-Quellcode:
IDemo = interface
  ['{AD1D916F-6AD4-4221-BBCC-1960A30110DB}']
  procedure WriteSth;
end;
-- Implementieren des Interfaces
Nachdem die zu implementierenden Interfaces festgelegt wurden, können sie von einem oder mehreren Plugins implementiert werden.
Für jedes Plugin wird dazu eine neue Klasse erstellt, die von der Klasse TBasePlugin und dem Interface erbt.

Beispiel:
Delphi-Quellcode:
TDemo = class(TBasePlugin, IDemo)
public
  procedure WriteSth;
end;
{ TDemo }
procedure TDemo.WriteSth;
begin
  WriteLn('Hello World!');
end;
Das erste Plugin ist fertig - jetzt muss es nur noch in das Package eingebunden werden.

- Zusammenstellung des Packages
-- Einbinden der Package-Unit
Damit das Package benutzt werden kann, muss erstmal die Unit plgPackage eingebunden werden.
Diese Unit verwaltet ein Package-Objekt und exportiert automatisch eine Funktion, die das Package-Objekt exportiert.

Beispiel:
Delphi-Quellcode:
uses
  [...], plgPackage, [...];
-- Konfigurieren des Packages
Der Host sollte wissen, mit welchem Package er es zu tun hat.
Es hängt aber auch nur vom Host ab, ob er unkonfigurierte Clients zulässt.

Es ist aber trotzdem immer besser, ein Package mit einer Version, Reversion und einer eindeutigen GUID zu versehen, damit es identifiziert werden kann.
Außerdem sollte auch der Autor angegeben werden.

Beispiel:
Delphi-Quellcode:
  PluginPackage.Version := 1;
  PluginPackage.Reversion := 0;
  PluginPackage.Author := 'Henning';
  PluginPackage.GUID := StringToGUID('{65FE93FD-3E7C-464F-9A95-1B66EEE3557C}');
Hinweis: eine eindeutige GUID kann in Delphi mit der Tastenkombination Strg+Shift+G erzeugt werden.

-- Befüllen des Packages mit Plugins
Anschließend kann das Package mit Plugins befüllt werden.
Dazu wird zu dem Plugin eine Plugin-Klasse erzeugt, die die Informationen zu dem Plugin bereithält.
Diese sind einmal der Namespace und Name des Plugins.
Der Namespace bestimmt die Gültigkeit des Namens - zwei Plugins mit selben Namen aber unterschiedlichen Namespaces gehören nicht zusammen.
Der Namespace verringert also die Gefahr von unbeabsichtigten Namenskonflikten.
Dann muss jedem Plugin ebenfalls eine eindeutige GUID zugeordnet werden, sodass es innerhalb des Plugin-Systems identifizierbar bleibt.
Der Parameter Data (der letzte Parameter, im unten stehendem Beispiel nicht angegeben) ist optional und kann weggelassen werden.
Beispiel:
  PluginPackage.AddPluginClass(TCustomPluginClass.Create(TDemo, 'demo', 'demo1', StringToGUID('{11139406-15BF-4769-87B6-5195A0AC6020}'))); Hinweis: es können beliebig viele Plugins zu einem Package zusammengefasst werden.

- Fertig! Der Client ist jetzt eingerichtet!
Die DLL kann jetzt vom Host geladen werden.

Host
- Festlegen der Interfaces
Damit der Host die Plugins bedienen kann, müssen ihm die implementierten Interfaces bekannt sein.
Sie können aber so abstrakt definiert sein, dass sie eine große Möglichkeit an Erweiterungen bieten.

- Erzeugen der PluginLibrary
Damit der Host PluginPackages laden kann, benötigt er erstmal eine PluginLibrary.
Diese ist in der Unit plgLibrary enthalten und muss manuell erzeugt und am Ende wieder freigegeben werden.

Beispiel:
Delphi-Quellcode:
uses
  [...], plgLibrary, [...];
[...]
var
  PluginLib: TPluginLibrary;
begin
  PluginLib := TPluginLibrary.Create;
  try
    [...]
  finally
    PluginLib .Free;
  end;
end;
- Einbinden der Packages
Schon jetzt können die Packages der Clients eingebunden werden.

Beispiel:
Delphi-Quellcode:
[...]
try
  PluginLib.AddPackage(TDLLLibPlgPackage.Create('projClient.dll', PluginLib));
finally
[...]
Dabei wird eine Klasse erzeugt, die das Package aus der DLL wrappt.
Auf diese Weise ist es auch Möglich, die Packages aus anderen Quellen zu beziehen (weiteres in den Demos).

- Benutzung der darin enthaltenen Plugins
Jetzt geht es los - die Plugin-Klasse kann herausgesucht und erzeugt werden! Dabei kommen jetzt die PInterfaces ins spiel, also Vorsicht!

Beispiel:
Delphi-Quellcode:
var
  DemoObj : TIntf;
[...]
  DemoObj := TIntf.ApplyPIntf(PluginLib.PlgClasses['demo', 'demo1'].CreatePlugin([]));
[...]
Um jetzt das Interface aus diesem DemoObj zu erhalten muss erstmal eine weitere Variable angelegt werden.

Beispiel:
Delphi-Quellcode:
var
  PIDemoIntf: ^IDemo; //Pointer auf das Interface IDemo
[...]
Über DemoObj kann diese Variable befüllt werden:
Delphi-Quellcode:
  [...]
  DemoObj.GetPIntf(IDemo, PIDemoIntf);
  [...]
Jetzt kann die Funktion WriteSth aufgerufen werden:
Delphi-Quellcode:
  [...]
  PIDemoIntf.WriteSth;
  [...]
Und zum Schluss darf nicht vergessen werden, das Demo-Plugin wieder freizugeben:
Delphi-Quellcode:
  [...]
  DemoObj.Free;
  [...]
Fertig! Das erste Plugin-System wurde benutzt und kann jetzt auch mit viel komplexeren Plugins bestückt werden! (siehe Demos)


Wie am Anfang gesagt:
Es ist ganz wichtig, das ihr, falls ihr Fragen habt, fragt!
Also kurz gesagt:
Bei Fragen: fragen!

In den Demos wird auch noch vieles klarer und verständlicher.
Sie sind nach ihrem Schwierigkeitsgrad geordnet und die letzten beiden enthalten nochmal (fast) alles zusammen.
 
DrD0j0
 
#21
  Alt 15. Mai 2011, 09:31
Gibt es Download noch irgendwo?
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf