Entwickler-Ecke
Sonstiges (Delphi) - Klasse in Dll packen?
Beiri22 - Fr 14.04.06 00:58
Titel: Klasse in Dll packen?
Genau das ist meine Frage: Kann man eine Klasse in eine Dll auslagern(evtl. ActiveX)? Wenn ja, wie macht man das, und wie bindet man sie wieder in ein Programm ein.
BenBE - Fr 14.04.06 08:54
Nimm anstatt einer DLL lieber ein Package... Das ist MZ\PE-Technisch das gleiche, jedoch wird bei deiner VMT und DMI-Table automatisch eine Korrektur vorgenommen, d.h. es funktioniert wenigstens ;-)
Achso, zur Nutzung:
Du schreibst einfach dein Hauptprogramm und bindest dabei die Unit, in der die Klasse deklariert ist, ein. Unter Projekt\Optionen schaltest Du "Mit Laufzeit-Packages compilieren" ein und ergänzt dort den Namen deiner zusätzlichen Packagedatei. Diese zusätzliche Package-Datei muss alle Units enthalten, die nicht in der VCL\RTL enthalten sind (sprich zu deinem Programm gehören) und Source enthalten, der von dieser Klasse referenziert wird.
Das Package-Konzept von Delphi ist kompliziert gemacht, relativ mächtig, aber blöd umgesetzt... Oft hat man damit mehr Aufwand als nötig, weshalb es sich nur in großen Projekten wirklich lohnt. Für Plugin-Schnittstellen, solltest Du dich einmal hier im Forum umschauen, da gab es IIRC mal ein Beispiel, wie das mit Packages zur Laufzeit nachladen für Plugins ging...
MrSaint - Fr 14.04.06 09:11
Es gäbe auch noch das Component Object Model (COM). Damit geht das auch. Die EXE kennt dann sozusagen die Header der Klasse in der DLL (in dem Fall läuft das dann aber nicht mit Klassen sondern mit interfaces, welche eben in der DLL realisiert werden). Ist aber etwas aufwändiger. Um da rein zu kommen, habe ich das Buch "COM/COM+/DCOM mit Delphi" von Andreas Kosch benutzt. Online fällt mir gerade keine gute Ressource ein...
MrSaint
MrSaint - Fr 14.04.06 09:34
Es geht noch viel einfacher, sozusagen mit OOP-Bordmitteln :D :
Du hast eine Klasse die du exportieren willst (z.B. ein PlugIn). Dann schreib erst mal eine neue Klasse in der die gleichen public Methoden etc vorkommen, nur dass alles abstrakt ist, also so:
Delphi-Quelltext
1: 2: 3: 4:
| TPlugInAbstract = class public procedure LegLos; abstract; end; |
Diese Klasse packst du in eine eigene Unit, welche sowohl die EXE, als auch die DLL kennt. Dann nimmst du deine Klasse von vorher her (die du ursprünglich exportieren wolltest) und leitest sie von der neuen, abstrakten Klasse ab. Diese Klasse packst du in die DLL.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| TPlugin = class (TPlugInAbstract) public procedure LegLos; end; ... Procedure TPlugin.LegLos; begin ... end; |
Nun schreibst du in die DLL noch eine Funktion wie diese:
Delphi-Quelltext
1: 2: 3: 4:
| function CreatePlugInObject: TPlugInAbstract; begin Result := TPlugInAbstract(TPlugin).Create; end; |
Und diese Funktion expoertierst du in der DLL.
Nun machst du es in deiner EXE einfach so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| function CreatePluginObject: TPlugInAbstract; external 'DLLNAME.dll';
var meinePlugInInstanz: TPluginAbstract; begin meinePlugInInstanz := CreatePlugInObject;
end; |
Und schon wäre es fertig :D
MrSaint
BenBE - Fr 14.04.06 09:54
@MrSaint: Diese Methode sollte man meiden, da es sehr witzige Effekte in Bezug auf den Is-\As-Operator provoziert ;-) So Fehler wie "TFont kann nicht zu TFont zugewiesen werden." ... Wie man sie eben kennt ^^
MrSaint - Fr 14.04.06 10:06
@BenBE: Was hat das damit zu tun? Diese von dir angesprochene Meldung kommt doch nur, wenn ich Assign aufrufe und für die entsprechende Klasse das Assign halt nicht implementiert ist, oder? Und wenn er festsetzt, dass wirklich jede abstrakte Methode auch implementiert werden muss, dann sollte das wunderbar funktionieren. Wenn er natürlich dann ein PlugIn schreibt, dass eine Methode nicht implementiert, kann es zu Problemen ("Abstrakter Fehler") kommen... Aber das ist dann ein Problem des PlugIn-Verfassers und nicht des Host-EXE-Verfassers...
MrSaint
BenBE - Fr 14.04.06 18:47
Nope ;-) Das ist sehr wohl ein Problem der Host-Anwendung: Jede DLL in Delphi enthält jegliche Klassen aus allen Units, die eingebunden wurden (in die DLL) Somit kommt es zu Code-Dopplungen und u.a auch zu der Situation, dass man in der DLL TObject.Create aufruft und meint, dieses ist mit dem TObject der Hauptanwendung kompatibel - da Delphi aber Klassen-Kompatibilität anhand der VMT-Adressen vergleicht (die ja bei DLL und EXE verschieden sind), bringt Delphi einen Fehler ...
Daher sollte man das Klassen-Sharing zwischen Host-Anwendung und jeglichen DLLs IMMER vermeiden, da es potenziell zu diesem Problem führt. Daher schreib ich meine Plugins (sofern nötig) immer über Packages, weil dann TObject wirklich immer eindeutig rtl70.$xp$14System@TObject ist.
MrSaint - Fr 14.04.06 19:22
Hmmm, okay... ich geb mich geschlagen :flehan: ;) :D
Beiri22 - Fr 14.04.06 21:10
Nochmal eine Frage zu deiner Methode MrSaint: Wie kann man die Klasse im Programm wieder freigeben?
MrSaint - Fr 14.04.06 21:32
Hmm.. Also erst mal hatte BenBE ja drauf hingewiesen, dass die Methode nicht wirklich gut ist... Aber freigeben tut man ein Objekt normalerweise mit .Free oder FreeAndNil aus der SysUtils-Unit ;)
Beiri22 - Fr 14.04.06 21:46
Das hab ich ja probiert, aber nachdem ich es im Programm freigegeben habe, ließ es sich immernoch
verwenden. Auch als ich eine Procedure in der Dll hatte und diese mit dem Objekt aufgerufen habe, so
dass die es in der dll freigibt, lief es noch weiter.
MrSaint - Fr 14.04.06 21:51
Also nachdem du Free aufgerufen hast ist der Speicher freigegeben. Es kann evtl. nur sein, dass der Speicher noch nicht von einem anderen Objekt überschrieben wurde.
Wenn du nur .Free aufgerufen hast und nicht FreeAndNil, zeigt deine Variable immer noch an die alte Speicherstelle und wenn die noch nicht überschrieben wurde kannst du auf das Objekt noch zugreifen. Sollte man aber eigentlich nicht machen ;)
MrSaint
Beiri22 - Fr 14.04.06 22:02
Ich schau mal nach und probiers
Beiri22 - Sa 22.04.06 15:43
Titel: An MrSaint und alle die es wissen
Hallo, ich habe mal noch eine Frage. Kannst du mir noch was über dieses COM erzählen,
klingt interessant. Wäre sehr nett.
Beiri22 - So 23.04.06 11:32
danke erstmal, ich schua mir die seite mal an.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!