Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Projektplanung und -Management (https://www.delphipraxis.net/85-projektplanung-und-management/)
-   -   Minimalistisches PlugIn-System (https://www.delphipraxis.net/162488-minimalistisches-plugin-system.html)

DeddyH 24. Aug 2011 17:15

Minimalistisches PlugIn-System
 
Ich trage mich mit dem Gedanken, ein kleines dynamisch erweiterbares Programm zu schreiben. Dazu habe ich mir bislang Folgendes überlegt:
- PlugIns liegen in Form von DLLs vor, welche eigentlich komplette Mini-Anwendungen sind
- diese liegen in einem fest definierten Verzeichnis
- beim Programmstart durchsucht die Hauptanwendung dieses Verzeichnis nach DLLs
- jede gefundene wird daraufhin überprüft, ob sie klar festgelegte Routinen exportiert
- falls dem so ist, wird sie einer Liste hinzugefügt und per Menü o.ä. zur Verfügung gestellt

Meine Frage dazu: ist das so machbar oder denke ich zu simpel? Welche Gefahren könnten u.U. lauern?
Dank im Voraus für Tipps und Anregungen.

Phoenix 24. Aug 2011 17:19

AW: Minimalistisches PlugIn-System
 
Das Prinzip funktioniert so ohne weiteres.
Allerdings klingt das zwar Simpel, aber der Teufel steckt im Detail (konkret: das Design Deiner 'klar festgelegten Routinen' bzw. die Kommunikation zwischen dem Plugin und dem Hauptprogramm). Das ganze ist also durchaus Aufwändiger als man anfangs denkt.

DeddyH 24. Aug 2011 17:22

AW: Minimalistisches PlugIn-System
 
Naja, mir ist schon klar, dass ich diese festgelegten Routinen nach Möglichkeit so definieren muss, dass später keine mehr dazukommen müssen. Aber bislang ist das Ganze ja eh nur ein Gedankenspiel, ich werde schon merken, wo ich mir wieder selbst ein Bein stelle :mrgreen:

Danke für Deine Antwort

ele 24. Aug 2011 17:29

AW: Minimalistisches PlugIn-System
 
Klingt ganz vernünftig.

Wenn dein Programm einfach alle DLLs in einem Verzeichnis versucht zu laden, muss man, um ein Plugin zu deaktivieren, das Plugin aus dem Verzeichnis herauskopieren oder umbenennen. Das ist je nach dem etwas umständlich, aber durchaus kein Blocker.

Bei Plugin-Systemen besteht ganz allgemein die Gefahr, dass die Plugin-Schnittstellen nicht genügend durchdacht werden. Das im Nachhinein zu ändern kann u.U. sehr mühsam sein (neu kompilieren aller Dlls), vorallem dann, wenn Dritthersteller anfangen Plugins beizusteuern.

Aus diesem Grund fände ich es wichtig ein System zu haben, dass dir die Version des Plugins (bzw. der Pluginschnittstelle) mitteilt. Dann kannst du notfalls eine Fehlermeldung ausgeben, falls eine Version von einem Plugin dagerkommt, dass dein Programm nicht unterstützt. Ich benutze in diesem Zusammenhang übrigens die Möglichkeit in der Versions-Information des Programmes (oder in diesem Fall DLL) einen neuen Schlüssel zu erstellen (z.B. PluginVersion).

DeddyH 24. Aug 2011 17:35

AW: Minimalistisches PlugIn-System
 
Sehr guter Einwand. Ich glaube zwar kaum, jemals in den Genuss zu kommen, dass sich ein Dritthersteller für meine Progrämmchen interessiert, trotzdem sollte man so etwas gleich am Anfang mit bedenken. :thumb:

ele 24. Aug 2011 17:37

AW: Minimalistisches PlugIn-System
 
Der "Dritthersteller" kann manchmal auch ein Alter Ego aus der Vergangenheit sein...

Stevie 24. Aug 2011 17:46

AW: Minimalistisches PlugIn-System
 
DLL basierte Plugin Systeme haben immer das Problem, dass man sehr schlecht komplexe Daten (Objekte) austauschen kann. Forms und Frames aus DLLs sind auch immer anfällig für Ärger. Dafür braucht man dann wieder BPLs, gegen die dein Programm und die Plugins gelinkt sind. Auch stellt sich die Frage, wieviel Wissen steckt in den Plugins? Stichwort Menü: hängen die Plugins sich selber da rein, weil sie das Menü übergeben bekommen (nicht gut) oder geben sie bloß eine Liste der Aktionen und die Anwendung hängt sie an. Wie stellt die Anwendung fest, wo sie hinkommen?

DSharp hat übrigens auch einige Units, mit denen man mit wenigen Handgriffen ein Plugin System bauen kann (angelehnt an MEF)

gsh 24. Aug 2011 17:49

AW: Minimalistisches PlugIn-System
 
Ich hab vor langer langer Zeit mal einen Codelib beitrag für ein kleines Plugin System geschrieben, vielleicht bringt dich das auf Ideen:
http://www.delphipraxis.net/73567-fl...ginsystem.html
Die Diskussion dazu ist auch recht interessant:
http://www.delphipraxis.net/74448-fl...iskussion.html

mschaefer 24. Aug 2011 18:16

AW: Minimalistisches PlugIn-System
 
Das Problem mit en PlugIn-Systemen ist, dass es meist Insellösungen sind. Um das vom Zeitaufwand in den Griff zu bekommen habe ich dies auch mit eigenständigen Anwendugen gemacht, die nur mit einem versteckten Aufrufparameter starteten. Der Datenaustausch läuft über xml-Files. Es war angedacht es über einen zentraln SOAP-Server zu steuern, aber dazu ist es nie gekommen. Also kurzum, ist ein gangbare Weg aber nicht der Weisheit letzter Schluß.

Grüße

FredlFesl 24. Aug 2011 19:01

AW: Minimalistisches PlugIn-System
 
Hi,

Ich habe mal Folgendes gemacht (alles so wie dein Vorschlag, also Verzeichnis durchsuchen, DLL laden usw.):
Jede DLL exportiert neben den Prozeduren "GetName" und "Initialize" (dazu später) beliebige Prozeduren.
Das Einzige, was diese beliebigen Prozeduren gemein haben, ist die Schnittstelle, denn sie sehen alle so aus:

Delphi-Quellcode:
Procedure SomeDLLProcedure (inParam : OleParam, var result, outParam : OleParam);


Ein- und Ausgabeparameter können also Arrays, Streams oder was auch immer sein. Result ist entweder unassigned oder enthält einen Fehler (gestreamed).

Aufgerufen wurden die über einen Plugin-Manager. Nehmen wir an, wir haben eine DLL "MyDLL" und die hat die Prozeduren "Proc1" und "Proc2". Dann rufe ich eine Prozedur der DLL so auf:
Delphi-Quellcode:
ThePluginManager.Call ('MyDLL.Proc1', inParam, result, outParam);


Ich habe damit also eine allgemeine Schnittstelle, die ich beliebig erweitern kann.
Der Plugin-Manager ist auch für die Kommunikation zwischen den DLL verantwortlich, denn er übergibt der DLL per exportierter 'Initialize' Prozedur eine Callback-Schnittstelle, sodaß auch ein Plugin über die gleiche -eben beschriebene Schnittstelle- ein anderes Plugin aufrufen kann. Oder definierte Routinen der Hauptanwendung..

Bei mir gab es in dem Sinne keine Hauptanwendung, denn die DLL implementierten einen Webservice, wobei die einzelnen 'Anwendungen' eben diese DLLs waren.

Desweiteren habe ich dafür gesorgt, das die DLL zur Laufzeit ausgetauscht werden können, ohne die Anwendung (den Service) beenden zu müssen. Die neue oder auszutauschende DLL kann man per TCP direkt in den Service impfen. Der packt die DLL in das Plugin-Verzeichnis, entfernt die alte Version und ab einem definierten Zeitpunkt werden alle Aufrufe an die neue DLL geleitet.

War ziemlich cool und hat auch gar nicht mal so viel Code.

r2c2 24. Aug 2011 19:37

AW: Minimalistisches PlugIn-System
 
Zum Design der Schnittstelle kannst du dir mal das angucken: http://www.christian-rehn.de/2011/08...er-api-design/ Fand ich ganz interessant.

mfg

Christian

Florian Hämmerle 24. Aug 2011 20:52

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von r2c2 (Beitrag 1119411)
Fand ich ganz interessant.

Der Googletalk breitet sich in der DP langsam aus. Hab ich vorhin auch gerade in nem Thread drauf verwiesen ;)

mfg Florian

BTT: Ansonsten wäre es vielleicht auch ne Möglichkeit, die Schnittstelle über eine der Scriptengines (SE2, PS, etc.) ansprechbar zu machen, dann braucht man nicht extra DLLs zu schreiben, sondern kann zum Produkt einen kleinen Plugin-Editor mitliefern. Vor allem littleDaves SE2 dürfte sich für diesen Zweck anbieten. Aus deiner Hauptanwendung machst du dann einfach bestimmte Objekte für die Scriptengine verwendbar und schon kann man in einem Object Pascal Dialekt eigene Plugins schreiben.

hanspeter 24. Aug 2011 21:45

AW: Minimalistisches PlugIn-System
 
Mit dll als Plugin kann man früher oder später auch ganz schön auf die Schn... fliegen.
Es verstecken sich 4 größere Problemchen.
1. Ich muss mit BPL arbeiten. Die müssen alle mit der gleichen Compilerversion in der gleichen Umgebung compiliert sein.
Wird (ausversehen) mal eine Init neu compiliert kommt gerne der Fehler ... wurde mit unterschiedlicher Version compiliert- und das erst beim Kunden.
2. Verwechselt jemand völlig gleichnamige BPL in unterschiedlichen Verzeichnissen, dann ist die BPL Hölle los.
3. Der Linker ist garnicht mehr so smart. Liegt auch daran, das im Initialisierungsteil einer Unit Code liegt.
Ich habe mein Programm mal auf einem Delphi-freien Rechner installiert und die von mir als Laufzeit angegebenen BPL dazu.
Danach musste ich noch 76 weitere BPL kopieren, darunter die BDE bis das Programm startfähig war.
4. Delphi registriert bei Windows Klassen über den Klassennamen.
Wird diese Klasse (z.B. Fastreport) in einer weiteren Dll verwendet, dann kommt die Fehlermeldung ...kann nicht geladen werden Klasse bereits registriert.
Der Fehler kommt irgendwann beim Kunden wenn in irgendeiner Konstellation dll A und B geladen werden und bei die gleiche Klasse verwenden wollen.
Die BPL ist so ein alter überflüssiger Zopf und Technologie des vorigen Jahrhunderts.

Um ein Plugin System in Delphi zu realisieren, haben sich bei uns 3 Wege als gangbar erwiesen.
1. Die Installation des Plugin als Comserver.
2. Die Installation des Plugin als Exe und der Verkehr über Aufrufparameter und Exitcode.
Werden mehr Daten benötigt, die Verbindung über ein Memmory mapped File.
Wenn es eine Client-Server Anwendung werden soll, erprobe ich gerade ein weiteres interessantes Verfahren.
Daten werden auf den Server zurückgeschrieben. Ein Trigger reagiert darauf und startet eine Storedprocedure. Diese macht nichts weiter als einen Job auf einen Stack abzulegen.
Dieser Job wird dann von dem Serverprogramm abgearbeitet.

Gruß
Peter

Stevie 25. Aug 2011 06:33

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von hanspeter (Beitrag 1119427)
Mit dll als Plugin kann man früher oder später auch ganz schön auf die Schn... fliegen.
Es verstecken sich 4 größere Problemchen.
1. Ich muss mit BPL arbeiten. Die müssen alle mit der gleichen Compilerversion in der gleichen Umgebung compiliert sein.
Wird (ausversehen) mal eine Init neu compiliert kommt gerne der Fehler ... wurde mit unterschiedlicher Version compiliert- und das erst beim Kunden.
2. Verwechselt jemand völlig gleichnamige BPL in unterschiedlichen Verzeichnissen, dann ist die BPL Hölle los.
3. Der Linker ist garnicht mehr so smart. Liegt auch daran, das im Initialisierungsteil einer Unit Code liegt.
Ich habe mein Programm mal auf einem Delphi-freien Rechner installiert und die von mir als Laufzeit angegebenen BPL dazu.
Danach musste ich noch 76 weitere BPL kopieren, darunter die BDE bis das Programm startfähig war.
4. Delphi registriert bei Windows Klassen über den Klassennamen.
Wird diese Klasse (z.B. Fastreport) in einer weiteren Dll verwendet, dann kommt die Fehlermeldung ...kann nicht geladen werden Klasse bereits registriert.
Der Fehler kommt irgendwann beim Kunden wenn in irgendeiner Konstellation dll A und B geladen werden und bei die gleiche Klasse verwenden wollen.
Die BPL ist so ein alter überflüssiger Zopf und Technologie des vorigen Jahrhunderts.

Dem kann ich nicht ganz zustimmen:
zu 1. Entwickelt euer Kunde eigene Plugins? Dann muss er natürlich die korrekten Dateien der BPLs bekommen. Wenn nicht, dann kann der "wurde mit unterschiedlicher..." Fehler nicht kommen. Oder die Anwendung wurde einfach schlampig getestet (auf einem Rechner, der keine Delphi Installation enthält)

zu 2. BPLs im Programm Verzeichnis -> keine Probleme

zu 3. Dann hast du wohl die falschen Runtime packages in deinem Programm angegeben oder in deiner eigenen BPL required. Ich hab selber schon erlebt, dass Leute null Plan von BPLs haben und was in welchen Packages zu finden ist, so dass total unnötige Packages required und demzufolge und ausgeliefert wurden.

zu 4. Genau deshalb benutzt man ja Runtime packages. In dem Fall würde man das Fastreport Package requiren.

Die BPL Technologie mag schon alt sein, deshalb ist sie aber nicht schlecht. Wie bei vielem kann man sich aber viel Ärger einhandeln, wenn man sie nicht zu beherrschen weiß.

Elvis 25. Aug 2011 06:34

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von Stevie (Beitrag 1119391)
DLL basierte Plugin Systeme haben immer das Problem, dass man sehr schlecht komplexe Daten (Objekte) austauschen kann. Forms und Frames aus DLLs sind auch immer anfällig für Ärger.

Es gibt in Windows einen binär kompatiblen Standard um Objekte auszutauschen: COM. Allerdings stinkt COM und zwar gewaltig.
Das schöne an diesem stinkenden Kadaver ist aber, dass es eben diesen Standard für Objekte hinterlassen hat. Delphis Interfaces implementieren immer IUnknown, die Grundlage aller COM Objekte.
Außerdem ist das Layout von Delphi-Interfaces kompatibel mit allen Sprachen, die IUnknown unterstützen.
Delphis OleVariant ist nur Compiler Magic über IDispatch, welches in der alten COM-Ära für dynamic scripting zuständig war.
Referenzzählung ist auch ein Standard in der COM-Welt, nicht unbedingt erzwungen und autom. wie in Delphi, aber dennoch weiß ein C++-Dev, der ein IUnknown sieht, dass und wie er _AddRef und Release bedienen muss.
Long story short:
Kombiniere klassische DLLs (nicht COM-infizierte Mistviecher!) mit Interfaces, und du bekommst eine Sprach- und Compiler- unabhängige PlugIn-Platform, bei der man nicht mit so grauenvoll plattgedrückten, absolut scheußlichen APIs rumwickeln muss. Damit meine ich die klassische Art, bei der Leute glauben alle exportierten Funktionen dürften nur aus primitiven Typen bestehen...

Die Hostapp würde kaum mehr als einen Service Locator übergeben, und auch einige sinnvolle Services wie Menüverwaltung, Dokumente, etc zur Verfügung stellen. Aber wirklich interessant wird es wenn Plugins selbst Services in den Locator registrieren können.
So dass Plugins von Knut Services von Plugins von Bert nutzen können...

Zitat:

Dafür braucht man dann wieder BPLs
BPLs sind etwas mit dem eigentlich NUR die Delphi-IDE sinnvoll arbeiten kann.
Denn BPLs haben solch komplett inakzeptable Einschränkungen wie: gleicher Compiler, gleiche BPLs, und alles nur Delphi!
Für die IDE mag das okay sein, die kann eh nur mit einer Delphi-Version auf einmal arbeiten und Delphi als erzwungene Voraussetzung tut der IDE auch nicht soo sehr weh. Aber dir selbst willst du solche eine blödsinnige Einschränkung nicht auferlegen.
Das hieße nämlich, dass du niemals wieder auf eine höhere Delphi-Version umsteigen kannst, und deine plugin-schreibenden User auch nicht, da plötzlich alles in sich zusammenstürzen würde. Prost Mahlzeit!

Sorry für die lange Predigt, aber ich halte BPL-Plugins für die digitale Version der jährlichen Grippewelle: Wenn man die Leute nicht regelmäßig impft werden sie doch krank (benutzen BPLs)...

Edit: Man sollte nirgends, in keinem einzigen Binäry, auf (Runtime-)BPLs verweisen.
Hast du auch nur ein einziges von den Viecher in deinem Prozess war's das. Dann kannst du sofort einpacken, was Flexibilität oder niedrigen Blutdruck angeht.
Eine einzige BPL wird als Abhängigkeit mindestens die RTL mitbringen, und ab dem Moment mussu auch die RTL einer ganz speziellen Delphi-Version mitliefern.
Wenn Teile dieser BPL auch nur Teil deiner PlugIn-API sind, kannst du NIE WIEDER auf eine neuere Delphi-Version wechseln ohne alle PlugIns zu töten.

Stevie 25. Aug 2011 06:43

AW: Minimalistisches PlugIn-System
 
Ich wüsste echt gerne, wie viele von den selbst gefrickelten Plugin Systemen, die ja ach so flexibel und Delphi unabhängig sind, tatsächlich auch so genutzt werden. In der Theorie ist das alles ganz toll. Aber die konkrete Anforderung zeigt letzlich, ob es tatsächlich externe Plugin Entwickler gibt, die andere Sprachen oder Delphi Versionen einsetzen. Und kommt mir jetzt nicht mit ja, im Firefox oder im Miranda kann ich das...

Elvis 25. Aug 2011 06:52

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von Stevie (Beitrag 1119445)
Ich wüsste echt gerne, wie viele von den selbst gefrickelten Plugin Systemen, die ja ach so flexibel und Delphi unabhängig sind, tatsächlich auch so genutzt werden. In der Theorie ist das alles ganz toll. Aber die konkrete Anforderung zeigt letzlich, ob es tatsächlich externe Plugin Entwickler gibt, die andere Sprachen oder Delphi Versionen einsetzen. Und kommt mir jetzt nicht mit ja, im Firefox oder im Miranda kann ich das...

Wir benutzen eine Oracle-IDE, die mit Delphi geschrieben ist.
Die nutzt zwar grausige. platte DLLs, aber genau deshalb konnte ich problemlos einige Plugins in C# schreiben.
Der Hersteller benutzt mittlerweile sicherlich nicht mehr Delphi 4 oder 5, mit dem die erste Version rauskam. Und man findet Plugins aus allen möglichen Sprachen für eben dieses Programm.
Nur um dir ein Beispiel zu nennen, welches auch ein Delphi-Host ist.

DeddyH 25. Aug 2011 07:27

AW: Minimalistisches PlugIn-System
 
:cyclops: hier ist ja richtig was los. Es ist vielleicht nicht richtig rübergekommen, aber mein Schwerpunkt liegt momentan weniger auf Flexibilität als mehr auf "Easy-to-use". Zu den zu exportierenden Funktionen, wie ich mir das bisher denke:
- "Titel" der Anwendung, ggf. Kurzbeschreibung
- eine Start-Routine
- ggf. Rückmeldung, wenn fertig

Das Hauptprogramm ermittelt also den Titel und fügt z.B. einen Menüpunkt in sein Menü ein. Die Kurzbeschreibung könnte dann für Hints o.ä. verwendet werden. Zusätzlich muss sie sich natürlich merken, welche DLL das war. Wird nun ein Menüpunkt angewählt, wird die DLL geladen, die Start-Routine aufgerufen und auf Rückmeldung gewartet (Message oder so), anschließend wieder entladen und fertig. So ist mein bisheriger Gedankengang.

hanspeter 25. Aug 2011 08:18

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von Stevie (Beitrag 1119443)

Oder die Anwendung wurde einfach schlampig getestet (auf einem Rechner, der keine Delphi Installation enthält)

zu 3. Dann hast du wohl die falschen Runtime packages in deinem Programm angegeben oder in deiner eigenen BPL required. Ich hab selber schon erlebt, dass Leute null Plan von BPLs haben und was in welchen Packages zu finden ist, so dass total unnötige Packages required und demzufolge und ausgeliefert wurden.
Wie bei vielem kann man sich aber viel Ärger einhandeln, wenn man sie nicht zu beherrschen weiß.

Ich möchte mir die Anwürfe und Unterstellungen ausdrücklich verbitten.
Genau wegen der beschriebenen Probleme haben wir die Neuentwicklung in Delphi schon vor längerer Zeit eingestellt.
Aber schön wenn Delphi noch von einigen Fanatikern verteidigt wird.

Peter

Stevie 25. Aug 2011 08:48

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von Elvis (Beitrag 1119446)
Wir benutzen eine Oracle-IDE, die mit Delphi geschrieben ist.

Toad? Und ja, wenn man eine kommerzielle Anwendung schreibt, die von Benutzern erweiterbar sein soll, dann stimmt das wohl. Daher sagte ich ja konkrete Anforderung.

Zitat:

Zitat von hanspeter (Beitrag 1119466)
Ich möchte mir die Anwürfe und Unterstellungen ausdrücklich verbitten.
Genau wegen der beschriebenen Probleme haben wir die Neuentwicklung in Delphi schon vor längerer Zeit eingestellt.
Aber schön wenn Delphi noch von einigen Fanatikern verteidigt wird.

Ich sprach von meinen Erfahrungen. Soll auch schon einige Delphi Entwickler gegeben haben, die große Anwendungen ohne Probleme mit Runtime Packages entwickelt haben.

Iwo Asnet 25. Aug 2011 11:03

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von DeddyH (Beitrag 1119448)
..als mehr auf "Easy-to-use". Zu den zu exportierenden Funktionen, wie ich mir das bisher denke:
- "Titel" der Anwendung, ggf. Kurzbeschreibung
- eine Start-Routine
- ggf. Rückmeldung, wenn fertig

Sowas haben wir auch: Ein Diagnosesystem für Maschinen. Das Plugin-System ist quasi eine Toolbox für unterschiedliche Diagnoseroutinen. Wenn der Techniker (Null Ahnung von Programmierung) irgendwo auf der Welt unterwegs ist und eine 'Spezialdiagnose' braucht, dann kann sich ein Programmierer hier kurz hinsetzen, schreibt die Diagnose als Plugin und schickt ihm die DLL. Der schmeisst sie ins Plugin-Verzeichnis, registriert die DLL und fertig. Wenn die DLL sich als praktisch erweist, kommt sie ins Standardportfolio.

Wir haben neben dem Namen und einer Kurzbeschreibung auch die Versionsnummer des Plugins mit aufgenommen.

Die Parametrierung des Plugins erfolgt über ein einfachen String der Form "Param1='1';Param2='xyz'". Dafür existiert der blöde TValueListEditor, der sonst zu nix zu gebrauchen ist. Wir wollten noch einen schicken tollen Parametereditor bauen, aber dafür müssten wir vom Plugin den Datentyp jedes Parameters wissen... Bisher hatte keiner Bock, das aufzubohren.

Es ist eine Anwendung, die an Spimplizität kaum zu über/unterbieten ist. Aber als Plugin-Framework ist es gut genug.

neo4a 25. Aug 2011 11:17

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von hanspeter (Beitrag 1119466)
Genau wegen der beschriebenen Probleme haben wir die Neuentwicklung in Delphi schon vor längerer Zeit eingestellt.
Aber schön wenn Delphi noch von einigen Fanatikern verteidigt wird.

Hallo Peter,

Dein Post-Counter zeigt, dass Du lange und aktiv hier im Forum unterwegs bist. Ein Wechsel der Entwicklungsumgebung weg von Delphi ist für mich nachvollziehbar.

Wie kommt es aber, dass aus einem aktiven Delphi-Entwickler und einem, der noch jetzt aktiv in einem Delphi-Forum unterwegs ist, einer wird, der seinen Mitstreitern bei Delphi-Lösungen Fanatismus vorwirft?

Wenn es nur eine ungeschickte Wortwahl ist, okay - aber ansonsten finde ich Deine Attitüde ("Ihr Armleuchter - ich weiß es besser, sage aber nicht was") befremdlich, um es einmal höflich zu formulieren.

ehX 25. Aug 2011 12:44

AW: Minimalistisches PlugIn-System
 
Ich verwende ein PlugIn-System meist so, wie es viele Spiele machen: keine DLL's, die nativen Code beinhalten, sondern das Hauptprogramm stellt alle für das PlugIn-System verfügbaren Funktionen als Lua-API zur Verüfgung, auf die man dann Scripten kann.
Die Plugins selbst bestehen dann aus einer oder mehreren lua-Dateien (oder compilierte luac-files) und haben zusätzlich eine TOC-File mit z.b. Versions-Informationen, welche Dateien zusammengehören, API-Version usw. Insgesamt so ähnlich wie z.B. das Addon-System von WoW.

Für mich war das ein gangbarer Weg für ein Plugin-System, da man so die volle Kontrolle vom Host hat, was ein Plugin darf und was nicht (keine Dlls, die geladen werden) Der Nachteil dabei ist natürlich, dass die interne API alle möglichen Dinge abdecken muss wie z.B. neue GUI-Elemente über die Lua-API dynamisch erstellen, binden etc. Das macht das Ganze natürlich aufwändiger.
Die Host-Anwendungen sind bei mir dann auch meistens in vollständiger Modul-Bauweise gebaut und werden über ein "Core-Plugin" verbunden.
So ist man auch flexibel, die Reihenfolge beim Start der eigenen Anwendung vollständig selbst festzulegen, welche Fenster geöffnet werden, was initialisiert wird etc. und alles über das Core-Plugin zu ändern.
(dazu muss natürlich die API jegliche GUI-create-Funktionen, Initialisierungs-Routinen der Module, Berechungsfunktionen o.Ä. nach aussen porten und braucht zumindest eine kleine Schicht, die das Window-Management übernimmt)

Ich weiss nicht, ob so ein Ansatz für dich in Frage käme, ich bin damit bis jetzt eigentlich immer ganz gut gefahren.

Florian Hämmerle 25. Aug 2011 12:51

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von ehX (Beitrag 1119571)
Ich verwende ein PlugIn-System meist so, wie es viele Spiele machen: keine DLL's, die nativen Code beinhalten, sondern das Hauptprogramm stellt alle für das PlugIn-System verfügbaren Funktionen als Lua-API zur Verüfgung, auf das man dann Scripten kann.
Die Plugins selbst bestehen dann aus einer oder mehreren lua-Dateien (oder compilierte luac-files) und haben zusätzlich eine TOC-File mit versions-Informationen, welche Dateien zusammengehören etc. So ähnlich wie das Addon-System von WoW.

Für mich war das ein gangbarer Weg für ein Plugin-System, da man so die volle Kontrolle vom Host hat, was ein Plugin darf und was nicht (keine Dlls, die geladen werden) Der Nachteil dabei ist natürlich, dass die interne API alle möglichen Dinge abdecken muss wie z.B. neue GUI-Elemente über die Lua-API dynamisch erstellen, binden etc. Das macht das Ganze natürlich aufwändiger.
Die Host-Anwendungen sind bei mir dann auch meistens in vollständiger Modul-Bauweise gebaut und werden über ein "Core-Plugin" verbunden.
So ist man auch flexibel, die Reihenfolge beim Start der eigenen Anwendung vollständig selbst festzulegen und über das Core-Plugin zu ändern.
(dazu muss natürlich die API jegliche GUI-create-Funktionen, Initialisierungs-Routinen der Module o.Ä. nach aussen porten)

Was auch meinen früheren Vorschlag der Verwendung von littleDaves ScriptEngine wieder ins Gespräch bringt =D

ehX 25. Aug 2011 12:55

AW: Minimalistisches PlugIn-System
 
Zitat:

Was auch meinen früheren Vorschlag der Verwendung von littleDaves ScriptEngine wieder ins Gespräch bringt =D
Jau, die ScriptEngine ist schon eine coole Sache!
Ich persönlich bin halt ein Lua-Fan, deswegen verwende ich das....auch wenn sich die ScriptEngine wohl für ein Delphi-Projekt insgesamt mehr anbietet..:-)

DeddyH 25. Aug 2011 13:01

AW: Minimalistisches PlugIn-System
 
Vielleicht sollte ich doch einmal erklären, wozu das Ganze eigentlich gut sein soll: meine Frau ist Lehrerin an einer hiesigen Förderschule und betreut dort die Werkstufe (die 16- bis 21-jährigen). Die Schüler dieses Alters lernen hauptsächlich, im täglichen Leben möglichst ohne fremde Hilfe zurecht zu kommen. Nun habe ich mir gedacht, ich könnte ein kleines Programm schreiben, das sich auf einfache Weise beliebig erweitern lässt. So könnte es z.B. Mini-Spiele und Mathe-Übungen anbieten (Wechselgeld zählen und solche Dinge). Man könnte natürlich auch viele kleine Exen erstellen und die dann einfach starten, ich möchte aber verhindern können, dass der Schüler Hans über den Explorer immer "Fang den Ball" startet, sondern nach 3 mal auch wieder etwas "Gescheites" machen muss. So kam ich auf die DLL-Idee. COM und *.bpl-Geschichten mögen ja durchaus ihre Berechtigung haben, sind mir für dieses Vorhaben aber viel zu oversized.

BUG 25. Aug 2011 13:20

AW: Minimalistisches PlugIn-System
 
Wenn es nur darum geht, dann könntest du das schnell das mit einer "Seriennummer" lösen, das einfach als Parameter übergeben wird.

zB. in der Form (salt + hash(salt + geheimnis + systemzeitInMinuten))
Im aufgerufenen Programm prüft du, ob das Passwort für diese oder die letzte Minute gültig war.

Besonders sicher ist es zwar nicht, aber einfach zu implementieren.


Interessant wäre aber auch, wenn man die "Startberechtigung" bei einem zentralen Server abruft. Von dort aus könnte man dann leicht Berechtigungen verteilen.

neo4a 25. Aug 2011 13:24

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von ehX (Beitrag 1119577)
Ich persönlich bin halt ein Lua-Fan, deswegen verwende ich das

Kannst Du dazu vielleicht ein simples Beispiel posten?

ehX 25. Aug 2011 13:27

AW: Minimalistisches PlugIn-System
 
Zitat:

Kannst Du dazu vielleicht ein simples Beispiel posten?
Von was jetzt genau? :-) Von einem Lua-Script?

Wenn von einem Addon, dann wird das nicht so "simpel" (zumindest nicht für einen kleinen Code-Block hier im Forum), da ja erst mal Lua initialisiert, die API registriert werden muss, die Deklarationen eingebaut usw.
Aber ich kann evtl. das die Tage mal zu einem Mini Demo-Projekt zusammenbauen.

neo4a 25. Aug 2011 13:32

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von ehX (Beitrag 1119601)
Zitat:

Kannst Du dazu vielleicht ein simples Beispiel posten?
Von was jetzt genau? :-) Von einem Lua-Script?

Wenn es hilft, die Umsetzung innerhalb Deines Plugin-Systems besser zu illustrieren, dann auch das.

ehX 25. Aug 2011 14:16

AW: Minimalistisches PlugIn-System
 
Also, generell ist es so (stark vereinfacht, und das ganze wird natürlich dann in Plugin- / API-Klassen gekapselt):


1) Du bindest erstmal die Lua-Header (Lua, LuaLib, LualAuxlib) ein.
In meinem Fall verwende ich für Delphi Lua 5.1.4.
Die Header liegen natürlich erstmal in C vor und müssen für Delphi konvertiert werden.
Das ist aber nicht sonderlich schwer, nur nervig :-)

2) Du deklarierst eine API-Funktion im Host, auf die Lua dann Zugriff haben soll, z.B. ein simples Showmessage:
Delphi-Quellcode:
function lua__Showmessage(L:Lua_State):Integer; cdecl ;
var
  i,pCount : Integer ;
  FAddOn : TehXAddon ;
begin
  // Ausführendes Plugin anhand des Lua-States ermitteln (diese Funktion ist dann in der Plugin -Klasse und ist für das Beispiel nun nicht sonderlich relevant)
  FAddOn := LuaHandler.FindAddOnByState(L) ;
 
  // Hole dir die Anzahl der von der Lua-Funktion auf dem Lua-Stack abgelegten Parameter
  // An der höchsten Position des Lua-Stacks befindet sich immer die Anzahl der Parameter auf dem Stack
  // In diesem Fall bedeutet jeder Parameter ein eigenes Showmessage
  pCount := lua_gettop(L) ;
 
  for i := 1 to pCount do
  begin
    // Parameter vom Lua-Stack holen, als string casten und per showmessage() ausgeben
    // Man zählt von der höchsten Lua-Stack-Position rückwärts
    Showmessage(lua_tostring(L,-i)) ;
  end;
 
  // Lua-Stack bereinigen => Parameter vom Stapel nehmen
  lua_pop(L,lua_gettop(L));
 
  // Rückgabewert 0 an Lua => Anzahl der von der Funktion auf den Stack gelegten Variablen
  // => Es wurde in diesem simplen Beispiel nichts abgelegt
  Result := 0;
end;

3) Man initialisiert im Host einen neuen Lua-State über die Lua-API über luaL_open() ;

4) Die vorhin deklarierte Funktion muss für den Lua-State registriert werden, damit Lua sie auch verwenden kann, das geht mit lua_register.
Wir nennen die Funktion in Lua simpel "Showmessage", wie im Delphi-Original
Delphi-Quellcode:
lua_register(FLuaState,PAnsiChar('Showmessage'),lua__Showmessage);


5) Jetzt kann man die Funktion in einem Lua-Script verwenden:
Folgender Aufruf in einem Lua-Script führt nun zwei Showmessage des Hostprogramms aus, einmal mit "Hello" und einmal mit "World"
Code:
Showmessage('Hello','World');
6) Das Host-Programm muss dazu gebraucht werden, den Lua-Code auch zu laden und auszuführen, das passiert ähnlich wie bei einer DLL (Datei laden und initialisieren über lua_dofile oder auch einzelne Funktionen, um Lua-Chunks auszuführen. Die Logik, wann was passiert, wird natürlich über deine Programmlogik (Eventhandler etc.) gesteuert)

Umgekehrt geht das ganze natürlich auch, der Host kann jegliche Funktionen eigenen API über Lua, und auch alle Funktionen, die in den Scripten deklariert wurden, über call /pCall aufrufen, aber das würde jetzt das kleine Beispiel sprengen :-)

Ich hoffe, die generelle Vorgehensweise ist nun klar? :-)
Durch die Implementierung von Lua kannst du also nun Funktionen als API schreiben, die der Script-Engine zur Verfügung stehen sollen und deine Kunden können daraus dann Plugins und Addons basteln. Wie diese Funktionen aussehen und was sie machen, ist nicht beschränkt, da sind dir alle Möglichkeiten offen.
Zudem hast du so auch die Möglichkeit, z.B. verschiedenen User-Accesslevels auch unterschiedliche API-Funktionen über lua_register() zu registrieren, so dass nicht jeder alles verwenden darf.

neo4a 25. Aug 2011 14:50

AW: Minimalistisches PlugIn-System
 
Dein Ansatz ist ganz ähnlich dem hier und warum sollte es auch nicht so sein.

Für LUA muss man ja immer eine DLL mit ausliefern, oder gibt es bereits eine OBJ-Lösung zum embedden?

AFAIK, läuft LUA auch unter iOS. Wäre interessant zu wissen, ob diese Einbindung unter allen Systemen funktioniert, die XE2 und LUA unterstützen.

Bei LUA wird neben der immensen Verbreitung immer die Performanz hervor gehoben. Gibt es aus Deiner Sicht noch weitere heraus ragende Merkmale?

Würde LUA nun auch noch mit verschiedenen Sprachsyntaxe unterstützen (Pascal, JavaScript, VB etc.) und Kaffee kochen können...

ehX 25. Aug 2011 15:04

AW: Minimalistisches PlugIn-System
 
Zitat:

Dein Ansatz ist ganz ähnlich dem hier und warum sollte es auch nicht so sein.
Stimmt, obwohl ich das bis jetzt gar nicht kannte :-D Da hatte wohl jemand eine ähnliche Idee. Und er ist wohl "weiter", dermaßen komplex wie diese ist meine Implementation noch nicht.
Als ich angefangen hatte, mein lua-basiertes Plugin-System für Delphi zu schreiben, gab es das noch nicht (oder ich hatte es nicht gefunden :-))
Sonst hätte ich wohl gleich das genommen :-D
Lustig, das dort vorgestellte Beispiel ist auch ein showmessage() und sieht fast identisch aus :-)

Zitat:

Für LUA muss man ja immer eine DLL mit ausliefern, oder gibt es bereits eine OBJ-Lösung zum embedden?
AFAIK über ein OBJ nein, aber es geht über Umwege: In die Applikation z.B. BoxedApp einbauen, die DLL als Resource einbinden und über BoxedApp dann virtuell laden.
Dann ist die Lua-DLL in der EXE und wird unter einer virtuellen Umgebung geladen. Habe ich testweise mal ausprobiert, klappt einwandfrei.

Zitat:

Bei LUA wird neben der immensen Verbreitung immer die Performanz hervor gehoben. Gibt es aus Deiner Sicht noch weitere heraus ragende Merkmale?
Ja, Lua ist sehr schnell. Was ich herausragend finde: Die Syntax finde ich gerade das Merkmal, das Lua herausragend macht. Sie ist einfach und auch für Nicht-Programmierer leicht erlernbar, so können viele sich ihr Addon zusammenstricken. Zudem ist die C-API Implementation über den Lua-Stack sehr transparent. Einmal verstanden sind neue Dinge im Host sehr schnell implementiert und man braucht nur sehr wenig Code, um eine Funktion als API nach aussen zu porten.
Weiteres Merkmal: Es gibt für Lua viele nette Erweiterungen, die man Einbinden kann. Zudem lässt sich genau kontrollieren, welche Std-Libs geladen werden können, einzelne Funktionen sperren ist auch leicht möglich etc.


Zitat:

AFAIK, läuft LUA auch unter iOS. Wäre interessant zu wissen, ob diese Einbindung unter allen Systemen funktioniert, die XE2 und LUA unterstützen.
Das interesisert mich auch. Aber erstmal sehen, wie XE2 und iOS überhaupt "zusammearbeiten" :-) Ich hab meine Finger an XE2 noch nicht dran, wie auch...

neo4a 25. Aug 2011 15:56

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von ehX (Beitrag 1119627)
Zitat:

Dein Ansatz ist ganz ähnlich dem hier und warum sollte es auch nicht so sein.
Stimmt, obwohl ich das bis jetzt gar nicht kannte :-D Da hatte wohl jemand eine ähnliche Idee. Und er ist wohl "weiter",

Ja, er übertreibt in jeder Beziehung. Er programmiert z.B. an 3 27"-Monitoren. Das ist ja pervers. Aber seine TKinect- Implementierung zur Fuchtelsteuerung hat schon was...

Zitat:

BoxedApp
Stimmt das habe ich hier schon einmal eingesetzt. Da ich aber nur noch "Multi-Plattform" denke, ist dieser Ansatz nicht so primär.

Zitat:

Zitat:

AFAIK, läuft LUA auch unter iOS. Wäre interessant zu wissen, ob diese Einbindung unter allen Systemen funktioniert, die XE2 und LUA unterstützen.
Das interesisert mich auch. Aber erstmal sehen, wie XE2 und iOS überhaupt "zusammearbeiten" :-) Ich hab meine Finger an XE2 noch nicht dran, wie auch...
Na hier hatten die bisherigen Veröffentlichungen zu FireMonkey etwas Substanz: Für iOS muss auf OSX-Seite noch XCode verwendet werden (u.a. wegen dieses ganzen Signatur-Geraffels). Heißt aber auch: Läuft LUA unter iOS und ist FPC in der Lage, Schnittstellen zwischen Pascal und ext. Libs wie LUA zu binden, dann, ja dann... Aber da hört leider das Substanzielle der derzeitigen schönen XE2-Marketingwelt auch schon wieder auf.

BUG 25. Aug 2011 17:00

AW: Minimalistisches PlugIn-System
 
Zitat:

Zitat von neo4a (Beitrag 1119624)
Bei LUA wird neben der immensen Verbreitung immer die Performanz hervor gehoben. Gibt es ... noch weitere heraus ragende Merkmale?

Portabilität:
http://www.lua.org/about.html
... builds out-of-the-box in all platforms that have an ANSI/ISO C compiler ...

Was man auch nicht vergessen sollte: da viele Spiele mit Lua gescriptet werden können, gibt es Leute, die sich damit in der Freizeit beschäftigen (Mods, AddOns, usw.).

neo4a 25. Aug 2011 21:00

AW: Minimalistisches PlugIn-System
 
Hast Du Infos, inwieweit das Einbinden ext. Libs wie LUA durch FreePascal auch unter OSX funktioniert?

Leider beschränken sich meine FreePascal-Cross-Plattform-Kenntnisse auf einen (seinerzeit durchaus erfolgreichen) Versuch beim Kompilieren meiner Firebird-UDF für Linux.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:20 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz