![]() |
Delphi-Version: 10 Seattle
DLL Callback Merkwürdigkeiten
Liste der Anhänge anzeigen (Anzahl: 1)
Moin... :P
Ich habe eine DLL, mit D5 erstellt, und eine Anwendung die auf Seattle compiliert ist. Die QT Auschnitte sind zu Testwecken vereinfacht. Was passieren soll: 1. DLL laden 2. procedure StartTransfer aufrufen 3. In der DLL: In StartTransfer den Wert "bearbeiten" 4. Als Callback zurückgeben. 5. In DoWork (Callback) die Werte anzeigen (MessageDialog) Fehler: Die Werte die ich erwartet habe sind "verschoben" bzw. nicht vorhanden. :? Wo hab ich den Denkfehler? DLL:
Delphi-Quellcode:
Anwendung:
uses
SysUtils, Classes, Windows, dbisamtb; procedure SetWorkCallback(CallBack: Pointer); stdcall; procedure StartTransfer(Path: PWideChar); stdcall; implementation var FWorkCallBack: procedure(TagName, TagValue: PWideChar) = nil; procedure SetWorkCallback(CallBack: Pointer); begin @FWorkCallBack := CallBack; end; procedure StartTransfer(Path: PWideChar); begin if Assigned(FWorkCallBack) then begin FWorkCallBack('bla', Path); // hier werden die Werte gefüllt end; end;
Delphi-Quellcode:
procedure TConfigTransfer.LoadDLL;
begin FDLLHandle := LoadLibrary(PChar(ExtractFilePath(ParamStr(0)) + conDBISAM_DLL)); if FDLLHandle <> 0 then begin @FSetWorkCallBack := GetProcAddress(FDLLHandle, 'SetWorkCallback'); if @FSetWorkCallBack <> nil then begin FSetWorkCallBack(@TConfigTransfer.DoWork); // Callback "registrieren" end; @FStartTransfer := GetProcAddress(FDLLHandle, 'StartTransfer'); end; end; procedure TConfigTransfer.StartTransfer; begin if @FStartTransfer <> nil then begin FStartTransfer('Blubb'); // Start end; end; procedure TConfigTransfer.DoWork(TagName, TagValue: PChar); var Name: string; Value: string; begin Name := TagName; Value := TagValue; MessageDlg(Name + ' ' + Value, mtInformation, [mbOK], 0); // siehe Bild1 (SOLL Name = 'bla', Value = 'Blubb') end; |
AW: DLL Callback Merkwürdigkeiten
Du übergibst einem Zeiger auf eine reguläre Prozedur eine Methode. Klappt es, wenn Du auch eine reguläre Prozedur daraus machst?
|
AW: DLL Callback Merkwürdigkeiten
Delphi-Quellcode:
ist eine normale Klassen-Methode nehme ich an? Das Problem ist, dass bei solchen Methoden immer ein versteckter
TConfigTransfer.DoWork
Delphi-Quellcode:
Parameter übergeben wird. Generell würde ich nicht einfach einen Pointer Parameter für den Callback verwenden, sondern einen Typedef verwenden:
Self
Delphi-Quellcode:
Des Weiteren würde ich aber auch generell keinen Methoden-Callback nehmen, da die Dll ja nichtmal weiß, welches Objekt zugeordnet ist und somit den
type
TMyCallback = procedure(Sender: TObject; A1, A2: PWideChar) of Object;
Delphi-Quellcode:
Parameter nicht sinnvoll füllen kann.
Self
Möglich wäre in deiner Anwendung die entsprechende Methode als
Delphi-Quellcode:
anzulegen. In diesem Falle verhält sie sich wie eine normale nicht-Objektgebundene Prozedur. Sehr oft haben Callbacks und deren Register-Funktionen einen Pointer Parameter, über den der Benutzer einen selbst-definierten Kontext weiterreichen kann. In diesem Falle sähe das zum Beispiel so aus:
class procedure Callback; static;
Delphi-Quellcode:
Und in der Dll dann entsprechend
type
TMyCallbackClass = class(TObject) public FIrgendwas: Integer; public class procedure Callback(Context: Pointer; A1, A2: PWideChar); static; end; ... MyCallbackClassInstance := TMyCallbackClass.Create; MyCallbackClassInstance.FIrgendwas := 42; SetCallback(@TMyCallbackClass.Callback, MyCallbackClassInstance) // <- 2. Parameter ist dein beliebig wählbarer Kontext
Delphi-Quellcode:
Jetzt kannst du in deiner Callback Funktion jederzeit wieder das dazugehörige Objekt ermitteln:
FWorkCallback(Context, 'bla', Path)
Delphi-Quellcode:
class procedure TMyCallbackClass.Callback(Context: Pointer; A1, A2: PWideChar);
begin ShowMessage(IntToStr(TMyCallbackClass(Context).FIrgendwas)); end; |
AW: DLL Callback Merkwürdigkeiten
Liste der Anhänge anzeigen (Anzahl: 1)
Danke...:P
Das Geheimnis war das:
Delphi-Quellcode:
:thumb:
// procedure DoWork(TagName, TagValue: PChar);
class procedure DoWork(TagName, TagValue: PChar); static; |
AW: DLL Callback Merkwürdigkeiten
Und, du hast über einen typlosen Zeiger sämtliche Typprüfungen umgangen.
Wenn man das nicht nacht, dann würde einem der Compiler auch brav sagen können, dass hier etwas nicht stimmt und sogar wo der Fehler liegt. |
AW: DLL Callback Merkwürdigkeiten
Moin...:P
Um diese Uhrzeit (ohne Kaffe) ist das mit dem Denken schlecht. Dann zeigt mir mal, wie es richtig geht. :thumb: Stichworte: - nicht Typlos - in der Klasse aber ohne class (Zugriff auf private Felder) - ohne Context Objekt Danke... |
AW: DLL Callback Merkwürdigkeiten
Statt sich mit Pointern und Methodenreferenzen herumzuärgern würde ich schlicht Interfaces benutzen. Dann übergibst du der DLL einfach nur dieses Interface und kannst dann aus der DLL dein Objekt in der Hostanwendung ganz normal über Methoden, Properties usw. ansprechen.
|
AW: DLL Callback Merkwürdigkeiten
Zitat:
Zur Typsicherheit:
Delphi-Quellcode:
Ich persönlich bin ein wenig von C-APIs (insbesondere der WinAPI) beeinflusst, weshalb ich diese Art von Context-Parametern gewöhnt bin und sie auch recht gerne verwende. Den untypisierten Pointer-Typ kannst du an dieser Stelle auch ohne weiteres mit dem Typ deiner Klasse austauschen (nur im Programm, nicht in der Dll), wenn du dich damit sicherer fühlst.
type
TMyCallback = procedure(Context: Pointer; P1, P2: PWideChar); stdcall; .. procedure SetCallback(Callback: TMyCallback; Context: Pointer); // <- TMyCallback statt Pointer
Delphi-Quellcode:
type
TMyCallback = procedure(Instance: TMyCallbackClass; P1, P2: PWideChar); stdcall; .. procedure SetCallback(Callback: TMyCallback; Instance: TMyCallbackClass); |
AW: DLL Callback Merkwürdigkeiten
Zitat:
denn so klappt mit der RTTI und gemeinsamen Ressourcen garnichts, was bei Klassen aber zwingend nötig ist. |
AW: DLL Callback Merkwürdigkeiten
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:53 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-2025 by Thomas Breitkreuz