Autor Beitrag
Wolf Beckmann
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Fr 27.12.02 14:38 
Ich möchte einer DLL die Adresse einer Methode übergeben, damit die DLL diese Aufrufen kann.

Beispiel mit einer Prozedur:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
// Procedur, die von der DLL aufgerufen werden soll:
Procedure Trc(Level:integer;Text:Pchar);
var i:integer;
    s:string;
begin
  for i:= 1 to length(funcstac) do s:= s+ '|   ';
  s:=s+string(Text);
  if level >= TRCLevel Then MainWindow.xTrc(s);
end;

//Deklarationen in der DLL:
const
  NTRC          =   1;

type
  TTRC          = Procedure (Level:Integer;Text:pchar);

var
  TRC         :TTRC;

//Übergabefunktion in der DLL:
procedure SetFunction (FuncNumber:Integer; Address:Pointer);
begin
  case FuncNumber of
    NTRC:         @TRC         := Address;
  end;
end;

//Übergeben der Procedur an die DLL aus dem Aufrufenden Programm:
SetFunction (1,@TRC);


Nach dem Aufruf der von SetFunction aus dem Programm herraus wurde der DLL die Prozedur TRC bekanntgegeben.
Nun kann die DLL die Prozedur TRC aufrufen.

Soweit so gut ...

Nun möchte ich aber nicht eine Prozedur übergeben, sondern eine Methode:
Also statt
SetFunction(1,@TRC)
so etwas wie
SetFunction(1,@Object.TRC)
DAS GEHT ABER NICHT!!!
Fehler: [Error] UPlugin.pas(173): Variable required

Hat jemand eine Idee ???

Ich habe auch schon Object.@TRC
und Object.MethodAddress('TRC') versucht.

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 27.12.02 15:09 
Hi!

Zunächst mal: Das Ansprechen von Objekten über die DLL hinaus ist nicht so einfach möglich. Dazu musst du Sharemem einbinden (im Forum suchen).
Übrigens stellst du dir das mit den Methoden schwieriger vor, als es ist.
Methoden sind bereits Pointer. Du musst einfach nur eine Prozedurvariable in der DLL erstellen (z.B. vom Typ TNotifyEvent, der häufigste Typ für die Ereignisgenerierung), der du dann die auszuführende Methode zuweist.

Nachtrag: Sehe gerade, daß es sich um eine normale Prozedur handelt, und nicht um eine Methode...

In deinem Falle:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
//Deklaration des zu übergebenden Prozedurtypen
type TMyProc = procedure(Level:integer;Text:Pchar); 

//Zu exportierende Prozedur in der DLL
procedure AssignMyProc(Proc:TMyProc);
begin
  MyProc:=Proc;
end;

//Die zugewiesene Prozedur innerhalb der DLL ausführen
procedure ExecuteMyProc;
begin
  if Assigned(MyProc) then
    MyProc;
end;



Cu, :)
Udontknow
Wolf Beckmann Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Fr 27.12.02 16:33 
Hi,

Vorab ein Dankeschöm, dass Du dich meinem Problem angenommen hast.

In dem Beispiel, dass ich oben angeführt habe benutze genau die Methode, die auch Du in Deinem Beispiel benutzt:
Das Zuweisen einer Prozedur.

Das ist ja auch einfach...
Ich möchte keine Objekte an die DLL übergeben um eben nicht Sharemem benutzen zu müssen, da ich eine offene (Sprach-unabhängig) Plugin-Schnittstelle für das Projekt zu erstellen.

Da ich die Plugins in meiner Applikation als Objekte verwalte, sollen die DLL auch diese Objekt-Methoden aufrufen können.

Beim Start der Applikation wird ein Dynamisches Array aufgebaut vom Typ TPlugin. TPlugin habe ich selbst definiert.
Für jede Plugin-DLL die gefunden wird, wird ein Objekt von diesem Typ angelegt und an das Array angehängt.
Es sollen nun Metoden des Objektes der DLL übergeben werden. Ich weis halt nicht wie ich die Adresse der Metode ermitteln kann....
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 27.12.02 17:08 
Hmm, ob das ohne Sharemem möglich ist, da bin ich mir nicht sicher. An deiner Stelle würde ich auch einen anderen Weg wählen, um Plugin-Fähigkeit zu erreichen: COM-Interfaces.

Aber nehmen wir mal an, dass man zumindest normale Prozeduren so angeben könnte.

So müsste deine DLL-Unit aussehen:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
//Deklaration des zu übergebenden Prozedurtypen 
type TMyProc = procedure(Level:integer;Text:Pchar); 

//Methoden-"merker"
var MyProc:TMyProc;

//Zu exportierende Prozedur in der DLL 
procedure AssignMyProc(Proc:TMyProc); 
begin 
  MyProc:=Proc; 
end; 

//Die zugewiesene Prozedur innerhalb der DLL ausführen 
procedure ExecuteMyProc; 
begin 
  if Assigned(MyProc) then 
    MyProc; 

exports AssignMyProc,ExecuteMyProc;
end;


Wenn du nun innerhalb deines Programmes die DLL dynamisch geladen hast und das dazugehörige Objekt erstellt hast, musst du nur noch die Zuweisung durchführen:

ausblenden Quelltext
1:
AssignMyProc(MyObject.ProcToAssign);					


Oder hast du Schwierigkeiten, die DLL dynamisch zu laden und die Methodenzeiger zuzuweisen?

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//Ist die DLL bereits geladen?
  if DLLHandle<>0 then exit;

  //DLL laden
  DLLHandle:=LoadLibrary('mydll.dll');

  //Wenn Handle erhalten, dann Prozedur-Referenzen bestücken
  if DLLHandle<>0 then
  begin
    @myproc1:=TryGetProcAddress(DLLHandle,'myproc1');
    @myproc2:=TryGetProcAddress(DLLHandle, 'myproc2');
    @myproc3:=TryGetProcAddress(DLLHandle, 'myproc3');
    ...
  end;


Cu,
Udontknow[/code]
Wolf Beckmann Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Fr 27.12.02 17:40 
Hi,
ich habe eben festgestellt, dass es anscheinend wegen des Ausfbaus von Objekten nicht so funktioniert wie ich mir das vorgestellt habe. Eine Methode hat immer eine feste Adresse, egal welches davon abgeleitete Objekt dazu benutzt wird. Deshalb kann man auch @TObject.Methode ermitteln aber nicht @Object.Methode. Warscheinlich wird Self auf den Stac gelegt um die Verbindung zu den Properties herzustellen.

Somit bleibt mir wirklich nur eine andere Methode für die Einbindung von Plugins. :(

Aber danke für Deine Hilfe!