![]() |
Zugriff auf lokale Variablen bei Callback aus DLL
Hallo.
Ich habe hier ein Verständnisproblem bzgl. DLL's und Callbacks. Also: Ich habe ein Host-Programm, das PlugIns nachladen kann. Diese PlugIns sind ganz normale Delphi-DLL's, die ein gemeinsames Interface implementieren. So weit so gut. Nachdem der Host ein PlugIn geladen hat, kann ich über eine PlugIn-Methode ein Callback registrieren, der dann im PlugIn aufgerufen werden kann. Soweit geht auch noch alles, soll heißen: PlugIn wird geladen, Callback wird registriert, eine PlugIn-Funktion wird aufgerufen die wiederum die Callback-Routine im Host aufruft. Nun mein Problem: Nehmen wir an, wir haben eine Form (TfrmMain) mit folgendem Aufbau:
Delphi-Quellcode:
Die CallbackProc ist die Methode, die vom Plugin aufgerufen wird. So, hier nun die Implementation der
TfrmMain = class(TForm)
procedure FormCreate(Sender: TObject); private { Private-Deklarationen } FLocalVar: string; procedure CallbackProc(ActionGUID: string; CallbackInfo: Pointer); public { Public-Deklarationen } end; Methode:
Delphi-Quellcode:
Das funktioniert....ABER...warum geht das hier nicht:
procedure TfrmMain.CallbackProc(ActionGUID: string; CallbackInfo: Pointer);
begin ShowMessage('Aufgerufen vom PlugIn!'); end;
Delphi-Quellcode:
Es scheint so, das ich hier KEINEN Zugriff auf die lokalen Variablen habe. Setze ich "frmMain.FLocalVar" davor, geht
procedure TfrmMain.CallbackProc(ActionGUID: string; CallbackInfo: Pointer);
begin ShowMessage(FLocalVar); end; es, da ich die Klasse explizit angebe, aber warum geht's nicht auch ohne.... ...und WIE LÖSE ICH DAS PROBLEM??? Die Variable "frmMain" gibts in meinem eigentlichen Programm nämlich gar nicht, da sie dynamisch in einem Skeleton (über eine ClassFunction) generiert wird. HILFE.... Lieben Gruß & Danke, kaju BDS2009 unter Windows7 |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Funktioniert es mit Self? Existiert eine Instanz (Objekt)?
|
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo.
Nein, auch mit SELF habe ich keinen Zugriff. Es kommt immer eine AV. Wenn ich wenigstens wüsste, warum das so ist. Ich habe echt das Gefühl, das ich innerhalb der im Host ausgeführten Callback-Funktion einen anderen Programmspeicher untergeschoben bekomme.... Aber danke 8-) Gruß, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Wie wird der Callback registriert? Wie ist der Funktionsprototyp der registrierungsfunktion? Wie wird der Callback aufgerufen?
Ach ja: Strings und DLL's. Hast du ShareMem oder FastMem eingebunden? |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Hallo.
Der Zugriff auch Strings ist kein Problem...das wird alles übergeben, egal wie lang. Habe statt "SimpleShareMem" auch schon mit FastMM4 und diversen Optionen rumexperimentiert, ohne Erfolg. Das PlugIn selber hält eine Liste der registrierten Callbacks. Hier mal der komplette Code:
Delphi-Quellcode:
Und hier die relevanten PlugIn-Stellen:
unit MainFrm;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, xpCore, xpPlugInMng; type { TfrmMain } TfrmMain = class(TForm) btnTest: TButton; edtFirstName: TLabeledEdit; edtLastName: TLabeledEdit; mmoLog: TMemo; PlugInManager: TxpPlugInManager; procedure FormCreate(Sender: TObject); procedure PlugInManagerLoadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); procedure PlugInManagerUnloadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); procedure btnTestClick(Sender: TObject); private { Private-Deklarationen } FLocalVar: string; procedure CallbackProc(ActionGUID: string; CallbackInfo: Pointer); public { Public-Deklarationen } end; var frmMain: TfrmMain; implementation uses SamplePlugInIntf; {$R *.dfm} {------------------------------------------------------------------------------- Procedure: TfrmMain.FormCreate Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: Sender: TObject Result: None -------------------------------------------------------------------------------} procedure TfrmMain.FormCreate(Sender: TObject); begin FLocalVar := 'In der Wüste steht ein Reddisch - ferdisch 8-)'; end; {------------------------------------------------------------------------------- Procedure: TfrmMain.PlugInManagerLoadPlugIn Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: Sender: TObject; PlugIn: TxpPlugIn Result: None -------------------------------------------------------------------------------} procedure TfrmMain.PlugInManagerLoadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); begin mmoLog.Lines.Add(Format('PlugIn "%s" geladen...', [PlugIn.FileName])); end; {------------------------------------------------------------------------------- Procedure: TfrmMain.PlugInManagerUnloadPlugIn Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: Sender: TObject; PlugIn: TxpPlugIn Result: None -------------------------------------------------------------------------------} procedure TfrmMain.PlugInManagerUnloadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); begin mmoLog.Lines.Add(Format('PlugIn "%s" entladen...', [PlugIn.FileName])); end; {------------------------------------------------------------------------------- Procedure: TfrmMain.CallbackProc Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: ActionGUID: string; CallbackInfo: Pointer Result: None -------------------------------------------------------------------------------} procedure TfrmMain.CallbackProc(ActionGUID: string; CallbackInfo: Pointer); var CallbackStruct: PCallbackStruct; begin ShowMessage('B: ' + Self.FLocalVar); CallbackStruct := CallbackInfo; ShowMessage('Callback called:' + #13#13 + Trim(CallbackStruct^.FirstName + #32 + CallbackStruct^.LastName)); end; {------------------------------------------------------------------------------- Procedure: TfrmMain.btnTestClick Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: Sender: TObject Result: None -------------------------------------------------------------------------------} procedure TfrmMain.btnTestClick(Sender: TObject); var SamplePlugIn: ISamplePlugIn; begin ShowMessage('A: ' + FLocalVar); if not(PlugInManager.LoadPlugIn('SamplePlugIn', ISamplePlugIn, SamplePlugIn)) then raise Exception.Create(PlugInManager.LastError); try SamplePlugIn.RegisterCallbackProc(CallbackProc); SamplePlugIn.Execute(edtLastName.Text, edtFirstName.Text); finally PlugInManager.UnloadPlugIn(SamplePlugIn); end; end; end.
Delphi-Quellcode:
UND:
unit SamplePlugInIntf;
interface uses xpPlugInIntf; type { TCallbackStruct } TCallbackStruct = record LastName: string; FirstName: string; end; PCallbackStruct = ^TCallbackStruct; { ISamplePlugIn } ISamplePlugIn = interface(IxpCustomPlugIn) ['{75C9A79A-DD40-4823-B7FC-17DB187B4526}'] function RegisterCallbackProc(CallbackProc: TxpPlugInCallbackProc): Boolean; function FindCallbackProc: TxpPlugInCallbackProc; procedure Execute(const LastName, FirstName: string); end; implementation end.
Delphi-Quellcode:
Bringt Euch das weiter?
unit SamplePlugInImpl;
interface uses Classes, xpPlugInIntf, xpPlugInImpl, SamplePlugInIntf; type { TCallbackProcStruct } TCallbackProcStruct = record CallbackProc: Pointer; end; PCallbackProcStruct = ^TCallbackProcStruct; { TSamplePlugIn } TSamplePlugIn = class(TxpCustomPlugIn, ISamplePlugIn) private { Private-Deklarationen } FCallbackProcs: TList; public { Public-Deklarationen } constructor Create; destructor Destroy; override; function RegisterCallbackProc(CallbackProc: TxpPlugInCallbackProc): Boolean; function FindCallbackProc: TxpPlugInCallbackProc; procedure Execute(const LastName, FirstName: string); end; implementation { TSamplePlugIn } {------------------------------------------------------------------------------- Procedure: TSamplePlugIn.Create Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: None Result: None -------------------------------------------------------------------------------} constructor TSamplePlugIn.Create; begin inherited Create; FCallbackProcs := TList.Create; end; {------------------------------------------------------------------------------- Procedure: TSamplePlugIn.Destroy Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: None Result: None -------------------------------------------------------------------------------} destructor TSamplePlugIn.Destroy; begin FCallbackProcs.Free; inherited; end; {------------------------------------------------------------------------------- Procedure: TSamplePlugIn.RegisterCallbackProc Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: CallbackProc: TxpPlugInCallbackProc Result: Boolean -------------------------------------------------------------------------------} function TSamplePlugIn.RegisterCallbackProc(CallbackProc: TxpPlugInCallbackProc): Boolean; var CallbackProcStruct: PCallbackProcStruct; begin try New(CallbackProcStruct); CallbackProcStruct^.CallbackProc := @CallbackProc; FCallbackProcs.Add(CallbackProcStruct); Result := True; except Result := False; end; end; {------------------------------------------------------------------------------- Procedure: TSamplePlugIn.FindCallbackProc Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: None Result: TxpPlugInCallbackProc -------------------------------------------------------------------------------} function TSamplePlugIn.FindCallbackProc: TxpPlugInCallbackProc; var i: Integer; CallbackProcStruct: PCallbackProcStruct; begin Result := nil; for i := 0 to FCallbackProcs.Count - 1 do begin CallbackProcStruct := PCallbackProcStruct(FCallbackProcs[i]); @Result := CallbackProcStruct^.CallbackProc; Break; end; end; {------------------------------------------------------------------------------- Procedure: TSamplePlugIn.Execute Author: Marc Hoffmann DateTime: 2009/12/10 Arguments: const LastName, FirstName: string Result: None -------------------------------------------------------------------------------} procedure TSamplePlugIn.Execute(const LastName, FirstName: string); var CallbackProc: TxpPlugInCallbackProc; CallbackStruct: TCallbackStruct; begin CallbackProc := ISamplePlugIn(Self).FindCallbackProc; if not(Assigned(CallbackProc)) then Exit; CallbackStruct.LastName := LastName; CallbackStruct.FirstName := FirstName; CallbackProc('12345', @CallbackStruct); end; end. Lieben Gruß, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Wie ist TxpPlugInCallbackProc definiert?
|
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Uppps....vergessen:
Delphi-Quellcode:
Gruß,
TxpPlugInCallbackProc = procedure(ActionGUID: string; CallbackInfo: Pointer) of object;
kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Liste der Anhänge anzeigen (Anzahl: 1)
Okay...da ich echt am verzweifeln bin, anbei mal das komplette Paket...wenn's läuft's, dürfen's alle benutzen 8-))
Lieben Gruß, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Das problem ist ein anderes. Der Callback erwartet eine FUNKTION, keine Methode eines Objektes.
Oder anders gesagt, der 'Self' pointer, der auf das Objekt verweits, und der als erstes (unsichtbares) Argument bei Delphi erwartet wird, ist NIL. Ich suche gerade mal eine Lösung dafür und melde mich dann wieder ;-) Edit: Hier haben wir den besagten Thread: ![]() |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Hallo.
Ich zitiere mal einen Satz auf "Findet Nemo": Zitat:
Ich versteh's hoffentlich, wenn das Problem gelöst ist 8-)) Vielen Dank für Deine Mühe, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
...okay...so ganz verstanden habe ich es jetzt aber nicht...wie müsste ich dann meinen Code ändern?
Vielen Dank, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Ganz einfach: (Freie)Funktion/Methode <> Methode einer Klasse.
Delphi-Quellcode:
unit MainFrm;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, xpCore, xpPlugInMng; type { TfrmMain } TfrmMain = class(TForm) btnTest: TButton; edtFirstName: TLabeledEdit; edtLastName: TLabeledEdit; mmoLog: TMemo; PlugInManager: TxpPlugInManager; procedure FormCreate(Sender: TObject); procedure PlugInManagerLoadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); procedure PlugInManagerUnloadPlugIn(Sender: TObject; PlugIn: TxpPlugIn); procedure btnTestClick(Sender: TObject); private { Private-Deklarationen } FLocalVar: string; public { Public-Deklarationen } end; var frmMain: TfrmMain; procedure CallbackProc(ActionGUID: string; CallbackInfo: Pointer); implementation uses SamplePlugInIntf; {$R *.dfm} procedure CallbackProc(ActionGUID: string; CallbackInfo: Pointer); var CallbackStruct: PCallbackStruct; begin ShowMessage('B: ' + frmMain.FLocalVar); CallbackStruct := CallbackInfo; ShowMessage('Callback called:' + #13#13 + Trim(CallbackStruct^.FirstName + #32 + CallbackStruct^.LastName)); end; ... |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Du übergibst nicht direkt Deine CallbackProc an die externe Dll, sondern die Rückgabe von MakeProcInstance(CallbackProc);
Die merkst Du Dir zudem vorher in einer Variable - und nachdem Du fertig bist und der Callback nicht mehr aufgerufen werden kann gibst Du diesen Pointer auch mit FreeProcInstance wieder frei. Sonst hast Du ein Memory-Leak von 15 bytes. |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Hallo...
Danke, das werde ich mal ausprobieren - ihr seid spitze 8-)) Gruß, kaju |
Re: Zugriff auf lokale Variablen bei Callback aus DLL
Nochmal Hallo.
Also, ich habe jetzt mein PlugIn-System umgeschrieben und siehe da, nun funktioniert der Zugriff auf lokale Variablen ohne Umweg 8-))) Ich muss mich auch nicht selber um die Allocation und Deallocation des Speichers kümmern...super 8-) Vielen Dank nochmal, kaju |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz