2013-08-22 15 views
5

Ich schreibe eine Delphi-DLL. In der Delphi-DLL möchte ich eine Callback-Funktion implementieren, diese Callback-Funktion sollte zum Aufrufer Delphi-Programm zurückrufen. Der Hauptzweck der Callback-Funktion besteht darin, dass eine bestimmte lange Operation in der DLL stattfindet, aber die Fortschrittsberichterstattung (über eine Fortschrittsleiste) und die Aufhebung der Operation sollten im aufrufenden Delphi-Programm erfolgen.Callback-Funktionalität zwischen Delphi DLL und Delphi EXE

Ich möchte einige Unterstützung erhalten, wie die Rückruffunktion innerhalb der DLL korrekt implementiert wird. Ich kann fortfahren, bis die Callback-Funktion zugewiesen von der EXE übergeben, aber ich weiß nicht, wie Sie einen Aufruf von der DLL selbst initiieren.

Dies ist die Definition Teil (verwendet von EXE und DLL):

uses Windows; 

Type 
    PTCallBackStruct = ^TCallBackStruct; 
    TCallBackStruct = packed record 
    Handle: THandle; 
    Caller: Pointer;   
    FileSize: LongInt; 
end; 

type 

TFunctionPointerType = function(ZCallbackRec: PTCallBackStruct): Longbool; 
    stdcall; 

type 
    PTDLLParamaters = ^TDLLParamaters; 
    TDLLParamaters = packed record 
    Handle: THandle; 
    Caller: Pointer; 
    CallbackFunction: TFunctionPointerType; 
end; 

var 
    DLLCallback: TFunctionPointerType; 

EXE-Datei:

uses ....  

type 

    function DLL_Callback(ZCallBackRec: PTCallBackStruct): LongBool; stdcall; 
    forward; 

    implementation 

    function DLL_Callback(ZCallBackRec: PTCallBackStruct): LongBool; stdcall; 
    begin 
     // progress reporting this function should be called back from 
     //the DLL. The Handle and Self parameter should help with identifying 
     // which object initiated the callback 
    end; 

über PTDLLParameters an die DLL übergeben, wie von der exe Delphi folgt :

// init callback 
DLLParameters := AllocMem(SizeOf(TDLLParamaters)); 
with DLLParameters^ do 
    begin 
    Handle := Application.Handle; 
    Caller := Self; 
    CallbackFunction:= DLL_Callback; 
    end; 

die DLL

..... 
    ..... 

Aufruf der DLL Laden

CompressionCreateLibrary(DLLParameters); 
    .... 

bestimmte Operationen

 Free DLL 
    .... 
    ..... 
    FreeMem(DLLParameters); 

DLL-Datei:

Diese Funktion sollte von bestimmten Teil der DLL aufgerufen werden den Fortschritt zurück zur EXE machen tatsächlicher Betrieb in Bezug auf:

function CallCallBackFromDLL(Size: integer): Integer; 
    begin 
     // 
     .... 
     set up callbackstruct 
     .... 
     // calling back 
     DLLCallback(CallbackStruct); 
     end; 

Ich denke, das Teil in Ordnung sein sollte:

// main init call assigning the callback function to the DLL 
function CompressionCreateLibrary(DLLParametersID: PTDLLParamaters): Integer; 

begin 

    DLLParametersID.CallbackFunction:= @DLLCallback; 

end; 

Bitte helfen Sie mir, wie Sie den Callback-Teil richtig in der DLL zu implementieren. Ein Beispielcode wäre wünschenswert. Während das Debuggen der Initialisierung funktioniert, funktioniert ein Rückruf jedoch nicht erfolgreich. Vielen Dank im Voraus.

+0

Ich habe keine Ahnung, was Sie fragen. Es gibt eine ziemlich große Menge an Code-Ausschnitten, die schwer zusammenzufügen sind. Und dann "schlägt ein Rückruf fehl". Äh, was bedeutet Versagen? Und was sagt dir dein Debugging? Bitte sagen Sie mir, dass Sie etwas Debugging durchgeführt haben. Andere Kommentare: 1. Verwenden Sie nicht verpackt. 2. Verwenden Sie nicht @, um prozedurale Variablen zu erhalten. –

+1

Das ist ** fast ** eine gute Frage. Sie haben Ihren Code gezeigt, und Sie haben erklärt, wofür jedes Bit verwendet wurde. Sie haben keinen irrelevanten Code eingegeben, aber Sie haben alle wichtigen Deklarationen angezeigt. Der Schlüssel, den Sie ** nicht eingeschlossen haben, ist eine Beschreibung dessen, was falsch ist. "Fails" ist nicht gut genug. Was passiert eigentlich und was haben Sie stattdessen erwartet? –

+0

Weitere Kommentare. Es gibt keine Notwendigkeit für Heap-Zuweisung, verwenden Sie eine Variable aus dem Stapel. Und Zeiger auf Datensätze zu legen ist grob. Ein const-Parameter des Datensatztyps ist sicherlich, was Sie brauchen. –

Antwort

4

Ihre Zuweisungsanweisung ist rückwärts. In der DLL-Funktion hält DLLParametersID die Informationen über den Rückruf, aber dann überschreiben Sie es mit Ihren globalen Variablen:

DLLParametersID.CallbackFunction:= @DLLCallback; 

Swap diejenigen DLLCallback zuweisen.

+0

Wenn ich dies tue, erhalte ich einen Compilerfehler (nicht genügend aktuelle Parameter) – fingomajom

+0

Es funktioniert, ich habe es ausgetauscht. Vielen Dank. – fingomajom

+0

Ich empfehle, dass Sie versuchen, Haltepunkte zu setzen und über Ihren Code zu gehen, und dann lernen, die Werte Ihrer Variablen zu betrachten. Wenn du die Richtung einer Aufgabe verpasst, vermisst du wahrscheinlich eine Menge von dem, was anderen Entwicklern als OFFENE Dinge erscheinen mag! Wenn Sie das Einzelschrittverfahren ausprobieren, können Sie vielleicht sehen, was wirklich passiert, wenn Ihr Code läuft. –