Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Klassen über Modulgrenzen hinaus instanziieren (https://www.delphipraxis.net/79171-klassen-ueber-modulgrenzen-hinaus-instanziieren.html)

DGL-luke 17. Okt 2006 15:22


Klassen über Modulgrenzen hinaus instanziieren
 
Hallo,

ich bin immer noch in den Weiten der DLL-Hölle unterwegs (und auf dem besten wege, sie mit einem kleinen team um einige schöne exemplare zu erweitern) und möchte für eine Art Plugin-System gerne in einer Dll eine Klasse deklarieren. Diese DLL wird dann aus einer anderen DLL (die wird von einem generischen Loader geladen, man kann sie also getrost als nicht die komplexität erhöhendes hauptmodul betrachten) dynamisch geladen und eine per Funktion aus der DLL gelieferte Klasse wird dann instanziiert. Ich werde das anhand eines kleinen code-beispiels erläutern:

Delphi-Quellcode:
//Deklaration
library Plugin1;

initialization

uses BaseClassUnit;

type
  TInherited = class(TBase)
    ...
  end;

function RetrieveClass: TBaseClass; export;

implementation

function RetrieveClass:TBaseClass;
begin
  Result := TInherited;
end;
Delphi-Quellcode:
uses BaseClassUnit;

//Benutzung
procedure CreatePlugin;
var ModuleRetrieveClass: function: TBaseClass; //salopp formuliert ;)
begin
//Modul laden, ModuleRetrieveClass-Prozedur zuweisen
...
//Klasse erstellen
NewPlugin := ModuleRetrieveClass.Create;
end;
Geht das? Geht das, aber ganz anders? Hilft mir da Delphi mit seinen Persistenzsachen (RegisterClass etc.)?

DGL-luke 20. Okt 2006 14:09

Re: Klassen über Modulgrenzen hinaus instanziieren
 
*push*
Niemand ein Statement für mich?

mkinzler 20. Okt 2006 14:11

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Wenn dir Delphi helfen soll, müsstest du imho Packages (Bpls) statt Dlls nehmen.

bepe 20. Okt 2006 17:28

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Das kann ich mir kaum vorstellen. Über BPL's vielleicht (oder sogar wahrscheinlich). Die Struktur bzw. Deklaration wird deinem Programm schon bekannt sein müssen.

Je, nachdem wie deine Anforderungen sind könntest du eine Plugin-Klasse in deinem Programm deklarieren, welche eigentlich gar nichts macht. Nur damit die Eigenschaften und Methoden bekannt sind. Dann könntest du diese Klasse in DLL's übernehmen und dort immer mit identischen Methoden aber unterschiedlicher Funtkionalität implementieren. Die Instanz würde dann in der DLL erzeugt und an dein Programm übergeben.

Wobei ich mir da nicht sicher wäre, dass es nicht zu unerwünschten Nebenwirkungen kommt.

SubData 20. Okt 2006 18:22

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Wenn sowohl deine Anwendung, als auch die DLL die genaue Struktur der Klasse kennen, quasi die Klasse in beiden definiert ist, dann kannst du sie wie einen "normalen" Datentypen als Ergebnis zurückliefern.

Es funktioniert, ob es Nebenwirkungen hat, kann ich dir nicht sagen :roll:

QuickAndDirty 20. Okt 2006 19:36

Re: Klassen über Modulgrenzen hinaus instanziieren
 
DLL Funktionen können zwar Objekte übergeben und empfagen, aber die Klassen müssen
auf beiden Seiten bekannt sein. Sie sind dann nur eingeschränkt ausserhalb des Moduls nutzbar,
weil die sogenanten RTTI im andere Modul nicht die selben sind. RTTI sind für alle von TPersistent
erbenden Objekte wichtig.

Der "IS" Operator arbeitet mit den RTTI , vor allem in Tpersistent.assign(bla:TPersistent) wird er benutzt.

Wenn du aber ganz neue Klassen baust , also von TObject erbst, dann lohnt es sich alle zugriffe in Interfaces
zu definieren. Besser also von TInterfacedObject erben und eigene Interfaces implementieren.


Ansonsten must du wohl mit BPLs arbeiten.

xaromz 20. Okt 2006 19:37

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Hallo,

wenn Du ein sauberes System brauchst und auf BPLs verzichten willst, dann kann ich Dir Interfaces empfehlen. Du definierst ein einInterface. und die DLL liefert Dir eine Instanz, die dieses erfüllt. Schon kannst Du im Hauptprogramm damit arbeiten, ohne dass Du wissen musst, wie das Ding intern aussieht. Ist vielleicht etwas aufwendiger zu implementieren, aber ich finde, das lohnt sich.

Gruß
xaromz

DGL-luke 20. Okt 2006 22:13

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Interfaces sind natürlich eine Möglichkeit. Dass mir das nicht von Anfang an klar war :wall:

@xaromz: Dein post impliziert, mit BPLs gehts?

xaromz 20. Okt 2006 23:39

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Hallo,
Zitat:

Zitat von DGL-luke
Interfaces sind natürlich eine Möglichkeit. Dass mir das nicht von Anfang an klar war :wall:

Besser spät als nie :wink: .
Zitat:

Zitat von DGL-luke
@xaromz: Dein post impliziert, mit BPLs gehts?

Wenn Du Deine Basisklasse in einem Package definierst und dann dieses sowohl im Hauptprogramm als auch in der DLL verwendest, benutzt Du ja in beiden Modulen die selbe RTTI. Dazu musst Du aber IMHO auch die RTL als Package verwenden, sonst fehlt Dir die Basis (TObject und so).

Ich muss aber dazusagen, dass ich nie viel mit mit Runtime-Packages gemacht habe. Als ich das gleiche Problem hatte, habe ich meinen gesamten Quellcode umgekrempelt und auf Interfaces umgestellt. Waren ja nur ~120 Klassen in 150.000 Zeilen :? . Seitdem ist das Leben aber viel einfacher. Ich finde auch die Interface-Deklaration für den Überblick über eine Klasse schön übersichtlich, da nur die öffentlichen Methoden drin stehen.

Gruß
xaromz

DGL-luke 21. Okt 2006 10:23

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Hmm... ich denke, ich müsste da noch mehr umkrempeln^^

Unter anderem benutze ich die RTTI um Objekte zu serialisieren... und um das hinzukriegen, hab ich ewig gebraucht ;)

QuickAndDirty 21. Okt 2006 18:54

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Der grund warum BPLs funktionieren ist weil sie im Speicherbereich der Anwendung geladen werden.
Damit das alles passt müssen BPLs und deine Anwendung z.b. Auch mit den Selben Defines kompiliert
sein. bzw. keinen Bedingt kompilierten Code enthalten. Das halte ich für extrem hinderlich.
Ich bin für interfaces, wenn möglich.

Deine RTTI werden immer noch zum Serialisieren taugen. Denn Die RTTI des DLL-Objects und die des Anwendungs-objects sind
die gleichen und sie sind auch im Zugriff. nur leider fragt der "is" operator ab ob die SELBEN sind...zwei gleiche RTTI zu
haben reicht ihm nicht aus, die Adresse an der sie zu finden sind ist entscheidend.

xaromz 21. Okt 2006 20:11

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Hallo,
Zitat:

Zitat von QuickAndDirty
Der grund warum BPLs funktionieren ist weil sie im Speicherbereich der Anwendung geladen werden.

Jede DLL befindet sich im gleichen Speicherbereich wie die aufrufende Anwendung. Der wahre Grund ist vielmehr, dass die gesamte Klassenhierarchie von beiden Modulen gemeinsam verwendet wird und somit identisch ist.

Gruß
xaromz

QuickAndDirty 24. Okt 2006 14:25

Re: Klassen über Modulgrenzen hinaus instanziieren
 
Nein, denn mehrere Anwendungen können eine DLL Benutzen. Aber es werden
wie ich hier erfahren habe gewisse teile der DLL bei benutzung (Copy on Write) kopiert.

Aber du hast natürlich recht das da eine BPL quasi Teil der Anwendung wird die Klassen
Hirarchie nicht nur die gleiche sondern auch die selbe ist, die RTTI funktionieren.

RTTI gibt es für jede Windows Anwendung oder DLL seperat.
Der Code in der System Unit legt das im übrigen
auch nahe.
Hier erkannt man eindeuteutig das ein Zeiger auf die RTTI den IS operator ausmacht.

Ich hab es nämlich ausprobiert und es Funktioniert wenn beide Module die Klassen Kennen
und kein IS operator Daten aus zwei verschiedenen Modulen vergleicht, ansonnsten geht es
nicht.
Fehler : "TStringlist ist nicht vom Typ TStringlist" (erst muste ich lachen, dann wurde es harte Arbeit)


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