5
votes

I am writting a Delphi DLL. In the Delphi DLL I would like to implement a callback function, this callback function should call back to the caller Delphi program. Main purpose of callback function is that certain long operation will happen in the DLL, but progress reporting (through a progressbar) and operation cancellation should happen in the caller Delphi program.

I would like to get some support how to implement correctly the callback function within the DLL. I can proceed until assigning the callback function passed from the EXE but i do nit know how to initiate a call from the DLL itself.

This is the definition part (used by EXE and 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 file:

 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; 

via PTDLLParameters passed to the DLL as follows from the Delphi exe:

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

loading the DLL

   .....
   .....

calling the DLL

   CompressionCreateLibrary(DLLParameters);
   ....

certain operations

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

DLL file:

This function should be called from certain part of the DLL making the progress back to the EXE regarding actual operation:

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

I think this part should be ok:

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

 begin

     DLLParametersID.CallbackFunction:= @DLLCallback;

 end;

Please help me out how to implement the callback part properly in the DLL. Some example code would be appreciated. While debuging initialization works fine, but making a callback fails. Thank you in advance.

1
I have no idea what you are asking. There's a rather large amount of code excerpts that are hard to piece together. And then "making a callback fails". Er, what does fails mean? And what does your debugging tell you. Please tell me you've done some debugging. Other comments: 1. Don't use packed. 2. Don't use @ to get procedural variables. - David Heffernan
This is almost a good question. You showed your code, and you explained what each bit was for. You didn't include irrelevant code, but you showed all important declarations. The key thing you didn't include is a description of what's wrong. "Fails" isn't good enough. What actually happens, and what did you expect to happen instead? - Rob Kennedy
More comments. There's no need for heap allocation, use a variable from the stack. And passing pointers to records is crude. A const parameter of record type is surely what you need. - David Heffernan
Dear Rob, Dear David, thank you for the comments. I will try to explain it further. I want to have a DLL for processing tstream contents basically compression and decompression, DLL should report back to the caller program the progress (bytes processed) in order to have this reporting i would like to use callback function. when I call CallCallBackFromDLL it just throws an exception. - fingomajom
It doesn't just throw an exception. It throws an exception of a specific class with a message. The fact that you don't tell us that info suggests you ignore it. Don't. Learn to understand it. And always include that info. - David Heffernan

1 Answers

4
votes

Your assignment statement is backward. In the DLL function, DLLParametersID holds the information about the callback, but then you overwrite it with your global variable:

DLLParametersID.CallbackFunction:= @DLLCallback;

Swap those to assign DLLCallback.