Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Flexibles Pluginsystem: Diskussion (https://www.delphipraxis.net/74448-flexibles-pluginsystem-diskussion.html)

cruiser 20. Jul 2006 05:42


Flexibles Pluginsystem: Diskussion
 
Flexibel heisst aus meiner Sicht aber auch, dass der Entwickler der Anwendung nicht wissen muss, was der Entwickler des Plugins mit dem Plugin in/an/mit/durch die/der Anwendung machen will. Soll heissen, woher weiss die Anwendung, welche Daten sie wann dem Plugin liefern muss?

Vielleicht löst du das erst mal noch :wink:


Dieses Thema bezieht sich auf diesen Codelib-Beitrag.
[edit=Phoenix]Codelib-Bezug eingefügt. Mfg, Phoenix[/edit]

gsh 20. Jul 2006 12:58

Re: Flexibles Pluginsystem
 
naja die daten sind immer die gleichen

Bsp von Trillian Load Befehl:
Zitat:

unsigned int struct_size; //<-- den braucht man nicht wirklich

/* Information given to the plugin
*/

char *config_directory;
char *skin_directory;
char *temp_directory;

plugin_function_send plugin_send; //Da wird die Callback übergeben

/* Plugin Fills out this information //de sachen kann das Plugin ausfüllen
*/

char guid[128];

char name[256];
char company[256];
char version[64];
char description[1024];

/* 2.0 information: given to the plugin //ab version 2 sind jetzt auch noch diese Werte enthalten
*/
char *global_config_directory;
char *trillian_directory;
char *language_directory;
Was dem Plugin übergeben wird ist fix im Programm drinnen. Aber wenn man jetzt ne Funktionen reinhat und ne Parameter dazu dann muss man die neuen Parameter einfach beim Record unten hinzufügen. Dann funktionieren die alten Plugins noch nur sie können nicht alles ausschöpfen. Aber wenn jemand ein Plugin programmieren möchte dann holt er sich die neue Plugin Unit und dann kann er die neuen werte auch nutzen ... des wegen flexibel

Des hab ich sogar vergessen zu sagen: Da dem Plugin ein Pointer von der Variable des Records übergeben wird. Somit kann das Plugin die Daten verändern und die Anwendung kann das dann ohne Probleme auslesen. z.b. Versions nummer des Plugins

kalmi01 20. Jul 2006 13:29

Re: Flexibles Pluginsystem
 
Hallo Alex,

Deine Idee ist nicht schlecht, hat aber einen gaaanz kleinen Haken:
Delphi-Quellcode:
PluginSend('Befehl an die Anwendung', nil);
'Befehl an die Anwendung' muss in der PlugIn-dll geparse't werden, was etwas Zeit kostet.

Ich hatte soetwas ähnliches in meinem Editor auch gemacht, je komplexer das System wurde, umso langsamer wurde es aber.
Allerdings ist Deine Methode unschlagbar flexibel.

gsh 20. Jul 2006 13:57

Re: Flexibles Pluginsystem
 
Zitat:

Zitat von kalmi01
Deine Idee ist nicht schlecht, hat aber einen gaaanz kleinen Haken:
Delphi-Quellcode:
PluginSend('Befehl an die Anwendung', nil);
'Befehl an die Anwendung' muss in der PlugIn-dll geparse't werden, was etwas Zeit kostet.

:gruebel: was meinst du? was kostet da zeit?
Des war nur ein Beispiel das das Plugin JEDERZEIT einen Befehl an die Anwendung senden kann damit die anwendung irgendwas macht.
Das kann man machen muss man aber nicht.

Zitat:

Zitat von kalmi01
Ich hatte soetwas ähnliches in meinem Editor auch gemacht, je komplexer das System wurde, umso langsamer wurde es aber.

hmm des es etwas langsamer wird ist klar aber des aus einen anderen grund

Zitat:

Zitat von kalmi01
Allerdings ist Deine Methode unschlagbar flexibel.

So war es auch gedacht :mrgreen:

kalmi01 20. Jul 2006 14:28

Re: Flexibles Pluginsystem
 
Zitat:

was meinst du? was kostet da zeit?
wenn Dein Prog
Delphi-Quellcode:
PluginMain(Befehl, Parameter);
aufruft, dann muss in "PluginMain" ja "Befehl" geparse't werden
Delphi-Quellcode:
if (Befehle = 'BringToFront') then machwas;
if (Befehle = 'GotoXY') then machwasanderes;
usw.
was nicht sooo performant ist, als wenn "machwas" oder "machwasanderes" direkt aufgerufen werden.
Selbst wenn man mit "Goto" aus der Schleife rausspringt.

Insbesondere wenn man
Zitat:

Dann müsst ihr nur noch eure Anwendung mit PluginBefehlen zupflastern.
z.b. wenn irgendein Menu geöffnet wird
das macht.

alias5000 20. Jul 2006 14:39

Re: Flexibles Pluginsystem
 
Zitat:

Zitat von gsh
hmm des es etwas langsamer wird ist klar aber des aus einen anderen grund

Erzähl mal :wink:

gsh 20. Jul 2006 15:41

Re: Flexibles Pluginsystem
 
aso jetzt versteh ich des wie du des meinst ... ja das war auch meine Überlegung das alles etwas langsamer wird

naja flexiblität hat seinen Preis :mrgreen:

noch ein Tipp:
Delphi-Quellcode:
if Befehl = '1' then
begin
  Bla;
  exit;
end;
if Befehl = '2' then
begin
  BlaBla;
  exit;
end;
if Befehl = '3' then
begin
  BlaBlaBla;
  exit;
end;
Dann wird sofort nachdem er den Befehl hat rausgesprungen (sowas wie goto)

DGL-luke 20. Jul 2006 15:49

Re: Flexibles Pluginsystem
 
dat würd ich anders machen ^^

Delphi-Quellcode:
case AnsiIndexStrings(Befehl,['1','2','3']) of
  0: Do_One;
  1: Do_Two;
  2: Do_Three;
end;
mMn sehr viel eleganter...

kalmi01 20. Jul 2006 15:51

Re: Flexibles Pluginsystem
 
Zitat:

Delphi-Quellcode:
if Befehl = '1' then
begin
  Bla;
  exit;
end;

Naja, dann könnte man aber auch gleich mit nem "case of" arbeiten.
"FindComponent" ist da wohl doch etwas performanter.

gsh 20. Jul 2006 15:58

Re: Flexibles Pluginsystem
 
ah des ist ja genial

ich hätte schon case genommen ... mein problem war einfach nur des case nur mit integer geht und die Funktion AnsiIndexStrings kannte ich nicht

@kalmi01: FindComponent? Wie soll des gehen?

gsh 20. Jul 2006 17:24

Re: Flexibles Pluginsystem
 
@DGL-luke: Ich wollt des gerade in mein TestPlugin einfügen doch leider kann ich die Funktion AnsiIndexStrings nicht finden. Naja daraus schliesse ich des du sie selber geschrieben hast. Ich bin nur etwas ratlos wie ich die Funktion am besten schreibe vorallem wegen dem zweiten Parameter :wall:


//edit: Habs geschafft:
Delphi-Quellcode:
function AnsiIndexStrings(Befehl : String; StringArray : array of String) : integer;
begin
  for result := 0 to Length(StringArray) - 1 do
  begin
    if Befehl = StringArray[result] then exit;
  end;
  Result := -1;  
end;

procedure PluginMain(Befehl : PChar; Parameter : Pointer); stdcall;
begin
  case AnsiIndexStrings(Befehl,['PluginInit', 'PluginStart', 'PluginStop', 'PluginFree']) of
    0://PluginInit
    begin
      PluginSend := TPluginRecord_PluginInit(Parameter^).PluginSend;
    end;
    1://PluginStart
    begin
    end;
    2://PluginStop
    begin
    end;
    3://PluginFree
    begin
    end;
  end;
end;
Kann man des noch irgendwie optimieren?

GimbaR 20. Jul 2006 17:49

Re: Flexibles Pluginsystem
 
Zitat:

Zitat von gsh
@DGL-luke: Ich wollt des gerade in mein TestPlugin einfügen doch leider kann ich die Funktion AnsiIndexStrings nicht finden. Naja daraus schliesse ich des du sie selber geschrieben hast. Ich bin nur etwas ratlos wie ich die Funktion am besten schreibe vorallem wegen dem zweiten Parameter :wall:

Ein Besipiel dafür findet sich in der CodeLib: *Klick*

Des Weiteren befindet sich in der Unit "StrUtils" eine Funktion die genau das Gleiche tut:
Delphi-Quellcode:
function AnsiIndexStr(const AText: string; var AValues: array of string): Integer;
so far

GimbaR

DGL-luke 20. Jul 2006 17:51

Re: Flexibles Pluginsystem
 
Ich bitte dich... ich würde hier doch nie meine eigenen FUnktionen kommentarlos hinklatschen^^

heisst halt nur n bischen anders: Delphi-Referenz durchsuchenAnsiIndexStr

@GimbaR: jaa....

gsh 20. Jul 2006 17:54

Re: Flexibles Pluginsystem
 
hehe jetzt hab ich es schon selber geschafft :mrgreen:
troztdem danke

Aber noch eine wichtige Frage kann man des noch optimieren ... vllt. mit ein bissi asm? (ich kann leider kein inline asm)


@DGL-luke: ja ich habs sie nur nicht gefunden (nicht mal mit Unit suchen)

Boombuler 21. Jul 2006 07:06

Re: Flexibles Pluginsystem
 
Hi,

alternativ könnte man auch statt eines Strings einen Integer übergebenm, und dort mit Konstanten oder Enumerationen für Befehle arbeiten. Das hätte folgende Vorteile:

1) Schnellere Überprüfung auf Gleichheit!
2) Keine Fehler durch Rechtschreibfehler oder der gleichen.

und wenn man neue Konstante immer nur Hinten anfügt hat man auch die Abwertskompatibilität berücksichtigt!

Greetz
Boombuler

PS: War nur so ne Idee :freak:

alias5000 21. Jul 2006 12:56

Re: Flexibles Pluginsystem
 
man könnte einen Pointer auf einen Record übergeben. Anonsten nur mit Integer als Enumeration zu arbeiten ist halt blöd, weil damit das übergeben von Parametern (fast) unmöglich ist.

Gruß alias5000

gsh 21. Jul 2006 20:14

Re: Flexibles Pluginsystem
 
Zitat:

Zitat von Boombuler
Hi,

alternativ könnte man auch statt eines Strings einen Integer übergebenm, und dort mit Konstanten oder Enumerationen für Befehle arbeiten. Das hätte folgende Vorteile:

1) Schnellere Überprüfung auf Gleichheit!
2) Keine Fehler durch Rechtschreibfehler oder der gleichen.

und wenn man neue Konstante immer nur Hinten anfügt hat man auch die Abwertskompatibilität berücksichtigt!

Greetz
Boombuler

PS: War nur so ne Idee :freak:

ja man könnte natürlich auch einen Integer übergeben.
ja es würde ein bisschen die Gischwindigkeit steigern
aber naja man könnte sich immer noch mit der Nummer vertippen

ABER des mit String Kommands zu machen hat menschliche vorteile ... "Was war Befehl 34345 noch mal *kratz*". aber wenn da steht "ProgrammStart" dann weiss man sofort bescheid :zwinker:

es steht natürlich jedem frei integer zu verwenden. aber ich bleibe bei Strings :zwinker:

xaromz 21. Jul 2006 20:21

Re: Flexibles Pluginsystem
 
Hallo,
Zitat:

Zitat von gsh
aber naja man könnte sich immer noch mit der Nummer vertippen

ABER des mit String Kommands zu machen hat menschliche vorteile ... "Was war Befehl 34345 noch mal *kratz*". aber wenn da steht "ProgrammStart" dann weiss man sofort bescheid :zwinker:

Wer sich schon 'mal Windows-Botschaften angesehen hat, der weiß, dass man für sowas Konstanten (mit aussagekräftigen Namen) definiert.

Gruß
xaromz

DGL-luke 21. Jul 2006 20:32

Re: Flexibles Pluginsystem
 
man könnte sogar das windows messaging missbrauchen und sich per Delphi-Referenz durchsuchenregisterwindowsmessage einen Integer zu einem string holen... (oder das ganze nachbilden).

aber konstante sollten hier reichen,.

gsh 21. Jul 2006 21:56

Re: Flexibles Pluginsystem
 
ok stimmt :thumb:

Am besten in der Gemeinsamen Unit (also die die man veröffentlichen sollte) einfach alle Konstanten definieren.

gsh 5. Aug 2006 00:22

Re: Flexibles Pluginsystem: Diskussion
 
so ich hab nochmal wegen dem Observer nachgedacht und mir ist dann ein super konzept eingefallen :mrgreen:
hab heut den ganzen Tag an diesem System programmiert.

Nun ist es ein Flexibles Observer Pluginsystem :cheers:

Die Flexiblität des Pluginsystems ist erhalten geblieben. Nur muss das Plugin beim starten der Anwendung bei meinem Observer anmelden. Sobald einmal angemeldet wird das Plugin bei diesem Ereignis benachrichtigt und kann sofort darauf reagieren.


*auf Uhr schau* (1:20 Uhr) Ich bin jetzt aber viel zu müde um ein Tutorial darüber zu schreiben, denn das ganze ist hoch komplex und wird wahrscheinlich nicht leicht zum erklären sein. Vielleicht komm ich morgen oder übermorgen dazu.

Angel4585 11. Apr 2007 11:23

Re: Flexibles Pluginsystem: Diskussion
 
Kann man eigentlich auch Plugins in einer anderen Sprache programmieren?

Also das das Programm in Delphi ist, das Plugin aber beispielsweise C++ oder so?

Ich weis dass es Records nur unter Delphi gibt(oder? :gruebel: )
Aber wenn man etwas anderes verwendet was andere Sprachen auch können müsste es doch gehen oder?

gsh 11. Apr 2007 14:44

Re: Flexibles Pluginsystem: Diskussion
 
sicher kann man das

und man kann auch records benutzen
weil records ist ja nichts delphi spezielles (außer der name) sonderen nur eine datenttyp wo mehere variablen nacheinander reingestopft werden.
In C++ und so gibt es des imho auch nur weiß ich gerade nicht wie es heißt

DGL-luke 11. Apr 2007 14:48

Re: Flexibles Pluginsystem: Diskussion
 
... records gibt es auch in C, die heißen da nur structs. und sind je nach cmopiler eventuell anders aligned, weshalb man in delphi packed records verwenden sollte.

Angel4585 11. Apr 2007 14:54

Re: Flexibles Pluginsystem: Diskussion
 
also wenn ich packed records verwende kann ih ohne größere Probleme die Plugins in anderen Sprachen schreiben?

Ihr sagt in C da heissen die Structs, C++, wo noch? Gibts da irgendwo Informationsquellen dafür?

gsh 11. Apr 2007 14:56

Re: Flexibles Pluginsystem: Diskussion
 
Mir ist gerade eingefallen des ich des selber mal in der DP gefragt hab: Klick Mich

Chaosente 2. Okt 2007 13:47

Re: Flexibles Pluginsystem: Diskussion
 
Wie sieht es denn aus mit dem Flexiblen Observer Pluginsystem Tutorial? Würde mich scon interessieren, da ich da im moment auch dran arbeite sowas zu machen. Wär cool, wenn du das noch mal machen könntest gsh...

gsh 2. Okt 2007 18:29

Re: Flexibles Pluginsystem: Diskussion
 
hmm jojo wenn ich dazu zeit hätte, aber da ich zur zeit 3,5 Jobs habe bin ich ehrlich gesagt zu erschöpft um mich da dran zu setzen
aber mal schaun wollt mir jetzt eh mal wieder urlaub gönnen :mrgreen:

LH_Freak 5. Nov 2007 16:50

Re: Flexibles Pluginsystem: Diskussion
 
heyho, also ich hab mich jetzt auch mal an ein Pluginsystem gesetzt...im Grunde ist das ne Mischung aus dem Tutorial von sakura und deiner Idee (denk ich zumindest oO ^^) also es ist auf jedenfall nichts besonderes denk ich...
es gibt eine Klasse TPlugin, von dem man seine Plugins ableiten kann...jedes Plugin enthält den Befehl Execute dem man dann die Parameter übergeben kann...dann gibts noch die Callbackprozedur Send, mit der dann Werte zurückgegeben werden können...sprich ich übergeb z.B. einem Downloadplugin den Befehl CMD_DOWNLOAD (einfach Konstanten) und dazu dann die Parameter als array of string, und in der DLL wird der Command ausgewertet, verarbeitet, und mit Send werden dann wieder Daten zurückgegeben, z.B. die Fortschrittsanzeige...in der Anwendung sieht dass dann z.B. so aus

Delphi-Quellcode:
uses {...} PluginDefinition;

var plugin1: TPlugin;

procedure RecieveProc(cmd: integer; parameter: array of string);
begin
  case cmd of
  // hier werden dann die commands ausgewertet
  CMD_SHOWMESSAGE: showmessage(parameter[0]);
  end;
end;

{...}

procedure TForm1.FormCreate(Sender: TObject);
var
  name: string;
begin
  plugin1 := TPlugin.Create;
  loadplugin('plugins/plugin.dll', plugin1);
  plugin1.Send := RecieveProc;

  plugin1.Execute(CMD_GET_NAME,['']); // nur ein Beispiel ;-)
end;
Die PluginDefinition.pas enthält alle Klassen und die FUnktion zum Laden des Plugins, sprich man braucht außer dieser Unit und der RecieveProc Prozedur nichts...in der DLL nimmt man ebenfalls die plugindefinition.pas, und erstellt sich eine Klasse...z.B.

Delphi-Quellcode:
{...}

TPlugin01 = class(TPlugin)
  public
    constructor Create(aParent: THandle); overload;
    function GetName: string; override; stdcall;
    function GetAuthor: string; override; stdcall;
    function GetComment: string; override; stdcall;
    procedure Execute(cmd: integer; parameter: string); override; stdcall;
  end;

constructor TPLugin01.Create(aParent: Cardinal);
begin
  inherited Create;
  Parent := aParent;
end;

function TPlugin01.GetName: string;
begin
  result := 'Testplugin';
  //showmessage('Testplugin');
end;

function TPlugin01.GetAuthor;
begin
  result := 'LH_Freak';
end;

function TPlugin01.GetComment;
begin
  result := 'Nur ein Test';
end;

procedure TPlugin01.Execute(cmd: Integer; parameter: string);
begin
  case cmd of
  CMD_GET_NAME: send(CMD_SHOWMESSAGE, ['Testplugin']);
  end;
end;

function LoadPlugin(Parent: THandle; var PlugIn: TPlugIn): Boolean; export;
begin
  try
    PlugIn := TPlugIn01.Create(Parent);
    Result := True;
  except
    Result := False;
  end;
end;

exports
  LoadPlugin name 'LoadPlugin';

begin
  //MessageBeep(0);
end.
Das mag jetzt zwar nicht soooo besonders anspruchsvoll und schwierig sein, und über Interfaces könnte man denk ich mal da schon bessere Sachen machen, aber es erfüllt seinen Zweck Prima...man definiert sich einfach seine Konstanten, und kann sich damit dann doch auch eine ganz flexible API erstellen...
Bei Bedarf kann ich die PluginDefinition.pas ja mal hier veröffentlichen :)

Gruß
Flo

P.S.: Ich werde das ganze demnächst in den MUH Messenger einbauen, da mich das schon irgendwie reizt auszuprobieren was damit alles geht, und das eignet sich ja mal wohl perfekt ;-)

Kedariodakon 5. Nov 2007 17:05

Re: Flexibles Pluginsystem: Diskussion
 
Für Plugins empfehlen sich Interfaces, gerade dann, wenn man auch Sprachenunabhängig arbeiten will (C, Delphi...)

Oder Packages, wenn man bei Delphi bleibt...

Denn mit sowas da
Delphi-Quellcode:
function LoadPlugin(Parent: THandle; var PlugIn: TPlugIn): Boolean; export;
begin
  try
    PlugIn := TPlugIn01.Create(Parent);
    Result := True;
  except
    Result := False;
  end;
end;
in dlls, kommt man sehr sehr schnell ans Limit der flexibilität...


Bye Christian

gsh 5. Nov 2007 17:06

Re: Flexibles Pluginsystem: Diskussion
 
Nein das Flexible Pluginsystem von mir beruht NICHT auf dem Tutorial von sakura (ich kannte des zu dem zeitpunkt noch nicht mal)

und du hast mehr von sakura reinkopiert kommt mir vor denn in meinem TUT ist keine einzige Klasse und der Parameter ist auch ein ganz ein anderer

LH_Freak 5. Nov 2007 17:50

Re: Flexibles Pluginsystem: Diskussion
 
Zitat:

Zitat von gsh
Nein das Flexible Pluginsystem von mir beruht NICHT auf dem Tutorial von sakura (ich kannte des zu dem zeitpunkt noch nicht mal)

und du hast mehr von sakura reinkopiert kommt mir vor denn in meinem TUT ist keine einzige Klasse und der Parameter ist auch ein ganz ein anderer

das war mir schon bewusst keine angst...ich hab ja auch gesagt, dass ich die beiden gemischt habe...auf jedemfall hatte ich das vor zu schreiben oO falls das nicht dasteht...und dein "Tut" (weiß nicht, ich empfand es mehr als Denkansporn statt einer anleitung) hat mich eher auf die idee gebracht das so zu machen, da das 1. wie gesagt leicht ist und 2. wenn man darauf verzichtet, dass mit anderen Sprachen Plugins gemacht werden können, ist das auch garantiert einfacher zu handhaben als Interfaces usw.

Zitat:

Zitat von Kedariodakon
Für Plugins empfehlen sich Interfaces, gerade dann, wenn man auch Sprachenunabhängig arbeiten will (C, Delphi...)

Oder Packages, wenn man bei Delphi bleibt...

Denn mit sowas da
Delphi-Quellcode:
function LoadPlugin(Parent: THandle; var PlugIn: TPlugIn): Boolean; export;
begin
  try
    PlugIn := TPlugIn01.Create(Parent);
    Result := True;
  except
    Result := False;
  end;
end;
in dlls, kommt man sehr sehr schnell ans Limit der flexibilität...


Bye Christian

Das kommt immer drauf an wie man flexibilität definiert...nachdem ich das ganz einfach verwenden kann, ohne etwas an der Basisklasse zu ändern, finde ich das schon flexibel genug...ob ich etz da dann c oder sonstwas nehmen kann ist mir eher egal..;)

Kedariodakon 5. Nov 2007 18:12

Re: Flexibles Pluginsystem: Diskussion
 
Problem dabei, die RTTI steht dir dabei nur bedingt zur Seite...
Was zu sehr vielen kleinen Problemen und AHA-Effekten führen wird.

Interfaces an sich sind gar nicht mal so schwer wie sie aussehen, zudem legen sie die Grundlage für schöne Erweiterungen, z.B. Com-Schnittstellen ec...

Bye Christian

eLse-maestro 25. Jan 2008 20:36

Re: Flexibles Pluginsystem: Diskussion
 
Delphi-Quellcode:
var
  TempPluginRecord_PluginInit : TPluginRecord_PluginInit;
  PluginMain : procedure(Befehl : PChar; Parameter : Pointer);
begin
  {Plugin laden und PluginMain procedure zuweisen}
  TempPluginRecord_PluginInit.PluginSend := PluginSend; //PluginSend?
  TempPluginRecord_PluginInit.NochEinPChar := 'blabla';
  PluginMain('PluginInit', @TempPluginRecord_PluginInit);
end;
Hey Leute, kann mir jemand diesen teil erklären? mit "PluginSend;"?
1.klappt das bei mir nicht, ist ja auch nicht verwunderlich da ich das nicht deklariert habe,
und 2. ich kopiere nicht gerne source wo ich nicht alles verstehe..

Chaosente 29. Jan 2008 12:27

Re: Flexibles Pluginsystem: Diskussion
 
ich hab da mal ne frage. oben wurde gasagt es empfiehlt sich interfaces zu verwenden. aber warum soll man dies tun, ich mein was hat das für nen vorteil oder warum stößt man dabei an die grenzen der flexibilität?

thabaker 29. Jan 2008 16:47

Re: Flexibles Pluginsystem: Diskussion
 
Meiner Erfahrung nach gibt es zwei Probleme bei der Plugin/DLL-Geschichte:

* Strings
* Objekte und Klassen

Strings und alle nicht Basistypen wie integer, char, pointer (damit auch pchar) [was ist mit variants?] verursachen in DLLs Probleme. Hängt mit dem Speichermanager zusammen, kann jeder nachlesen, steht da wenn man eine neue DLL erstellt. Lösung hier ein anderer Speichermanager.

Bei Objekten und Klassen ist das ganze schon schwieriger zu lösen. Delphi macht es mit den Laufzeit Packages. Der Kern des Problems liegt darin, dass Delphi wissen muss dass ein "TObject" aus der Anwendung auch ein "TObject" aus der DLL ist. Was ja nicht der Fall sein muss, wenn die beiden mit verschiedenen Versionen erstellt wurden. Also wirft das hier erst einmal eine Exception:

Delphi-Quellcode:
  // code in der Anwendung, ObjektAusDLL wurde zuvor von der DLL initialisiert
  // z.B. mit ObjektAusDLL := TFormDLL.create( nil); return ObjektAusDLL
  if not(ObjektAusDLL is TObject) then raise Exception.create('Nicht mit Anwendungs-RTL kompatibel');
  // z.B.
  ObjektAusDLL.Parent := self;
Das zieht sich durch die ganze Klassenhierarchie und macht sich immer wieder durch Laufzeitfehler bemerkbar.
Die Lösung hier sind Interfaces, so zwar konsequent so, dass die Anwendungs-RTTI und die DLL-RTTI nicht miteinander in Berührung kommen. Denn Interfaces nutzen GUID's, die Sprachunabhängig definiert sind und so beliebig funktioneren.

D.h. man hat am besten als Include oder "interface"-Unit
Delphi-Quellcode:
  // ['{3F2504E0-4F89-11D3-9A0C-0305E82C3301}'] ist die GUID für das interface
  // kopiert aus dem wikipedia Artikel zu "Globally Unique Identifier"
  IUnserInterface = interface ['{3F2504E0-4F89-11D3-9A0C-0305E82C3301}']
und bindet diese sowohl in die Anwendung als auch in die DLL ein. Das ist wichtig damit die GUID in beiden identisch sind.
damit ist eine Abfrage erfolgreich:
Delphi-Quellcode:
  dllInstanz := GetDLLInterface;
  if dllInstanz is IUnserInterface then ShowMessage( 'Alles ok');
Man abstrahiert demnach das Identifizieren von gleichen Typen auf eine compiler- und plattformunabhängige Art.

ACHTUNG: Damit ist es aber immer noch nicht möglich Steuerelemente die in der DLL erstellt werden in der Anwendung zu benutzen! Ein Panel aus der DLL wird nicht auf einer Anwendungsform korrekt funktionieren, da die interne Struktur auf oben genannte Probleme keine Rücksicht nimmt!

seim 3. Mai 2009 10:34

Re: Flexibles Pluginsystem: Diskussion
 
Ok das ist zwar alles schön und gut aber.. wie kann man eine DLL zur Laufzeit laden und das noch mit flexiblem Dateinamen oO?

Nur mal so als Beispiel:
Delphi-Quellcode:
function IcmpCreateFile : THandle; stdcall; external 'icmp.dll';
Das steht im interface Bereich.. wie bekomme ich so ein "icmp.dll" dynamisch zugeordnet?

mschaefer 3. Mai 2009 11:08

Re: Flexibles Pluginsystem: Diskussion
 
Mir stellt sich da die Frage wie ich so ein Plugin in die Menüstruktur / Befehlstruktur einfüge:

Das Plugin muß eine Anmelderoutine haben wo es in Listenform angibt welche Befehle es anbietet und welche Menuenamen diese Befehle haben.
Eine Andere Vairante ist das es selbst ein Panel anbietet wo die einzelnen Befehle als Ereignisse hinterlegt sind. Bei anmelden des Plugins wird dann der Parent auf ein Panel der Hauptanwendung gelegt...

Grüße // Martin

gsh 3. Mai 2009 12:39

Re: Flexibles Pluginsystem: Diskussion
 
Zitat:

Zitat von seim
Ok das ist zwar alles schön und gut aber.. wie kann man eine DLL zur Laufzeit laden und das noch mit flexiblem Dateinamen oO?

Nur mal so als Beispiel:
Delphi-Quellcode:
function IcmpCreateFile : THandle; stdcall; external 'icmp.dll';
Das steht im interface Bereich.. wie bekomme ich so ein "icmp.dll" dynamisch zugeordnet?

Bitte benutze die Suchfuntion Hier im Forum suchendll dynamisch laden


Zitat:

Zitat von mschaefer
Mir stellt sich da die Frage wie ich so ein Plugin in die Menüstruktur / Befehlstruktur einfüge:

Das Plugin muß eine Anmelderoutine haben wo es in Listenform angibt welche Befehle es anbietet und welche Menuenamen diese Befehle haben.
Eine Andere Vairante ist das es selbst ein Panel anbietet wo die einzelnen Befehle als Ereignisse hinterlegt sind. Bei anmelden des Plugins wird dann der Parent auf ein Panel der Hauptanwendung gelegt...

Grüße // Martin

da musst du dir selbst was überlegen aber so zur anregung:
1. Du könntest für Plugins einen befehl bereitstellen der das MenuItem erstellt und verschiedene erreignisse zurückgibt.

2. Oder was glaube ich einfacher ist das du das Parent Object auf Anfrage übergibst und sie dann selber sich eine menü struktur anlegen können.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:25 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