Einzelnen Beitrag anzeigen

thabaker

Registriert seit: 1. Jul 2007
50 Beiträge
 
Turbo Delphi für Win32
 
#36

Re: Flexibles Pluginsystem: Diskussion

  Alt 29. Jan 2008, 17:47
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!
  Mit Zitat antworten Zitat