Delphi DLL 和 Delphi EXE 之间的回调功能

Posted

技术标签:

【中文标题】Delphi DLL 和 Delphi EXE 之间的回调功能【英文标题】:Callback functionality between Delphi DLL and Delphi EXE 【发布时间】:2013-08-22 11:18:34 【问题描述】:

我正在编写一个 Delphi DLL。在Delphi DLL中我想实现一个回调函数,这个回调函数应该回调给调用者Delphi程序。回调函数的主要目的是在DLL中会发生某些长时间的操作,但进度报告(通过进度条)和操作取消应该发生在调用者Delphi程序中。

我想获得一些关于如何在 DLL 中正确实现回调函数的支持。我可以继续分配从 EXE 传递的回调函数,但我不知道如何从 DLL 本身发起调用。

这是定义部分(EXE和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 文件:

 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; 

通过 PTDLLParameters 从 Delphi exe 传递给 DLL 如下:

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

加载 DLL

   .....
   .....

调用 DLL

   CompressionCreateLibrary(DLLParameters);
   ....

某些操作

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

DLL 文件:

这个函数应该从 DLL 的某些部分调用,使实际操作的进度返回到 EXE:

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

我觉得这部分应该没问题:

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

 begin

     DLLParametersID.CallbackFunction:= @DLLCallback;

 end;

请帮助我如何在 DLL 中正确实现回调部分。一些示例代码将不胜感激。虽然调试初始化工作正常,但进行回调失败。提前谢谢你。

【问题讨论】:

我不知道你在问什么。有相当多的代码摘录很难拼凑在一起。然后“进行回调失败”。呃,失败是什么意思?你的调试告诉你什么。请告诉我你已经做了一些调试。其他cmets: 1.不要使用包装好的。 2.不要使用@来获取过程变量。 这是一个几乎的好问题。您展示了您的代码,并解释了每个位的用途。您没有包含不相关的代码,但您显示了所有重要的声明。您没有包含的关键内容是对问题的描述。 “失败”还不够好。实际发生了什么,您预计会发生什么? 更多cmets。不需要堆分配,使用堆栈中的变量。传递指向记录的指针很粗糙。记录类型的 const 参数肯定是你需要的。 亲爱的 Rob,亲爱的 David,感谢 cmets。我将尝试进一步解释。我想要一个用于处理 tstream 内容的 DLL,基本上是压缩和解压缩,DLL 应该向调用程序报告进度(处理的字节数),以便有这个报告我想使用回调函数。当我调用 CallCallBackFromDLL 时,它只会引发异常。 它不只是抛出异常。它抛出带有消息的特定类的异常。您没有告诉我们该信息的事实表明您忽略了它。不。学会理解它。并始终包含该信息。 【参考方案1】:

你的赋值语句是落后的。在 DLL 函数中,DLLParametersID 保存有关回调的信息,但随后您将其覆盖为全局变量:

DLLParametersID.CallbackFunction:= @DLLCallback;

将这些交换到 assign DLLCallback

【讨论】:

如果我这样做,我会收到一个编译器错误(没有足够的实际参数) 我建议您尝试设置断点并单步执行您的代码,然后学习查看变量的值。如果您错过了分配的方向,您可能会错过很多其他开发人员认为是显而易见的事情!如果您尝试单步操作,也许您可​​以看到代码运行时真正发生的情况。

以上是关于Delphi DLL 和 Delphi EXE 之间的回调功能的主要内容,如果未能解决你的问题,请参考以下文章

给Delphi程序添加版本信息(EXE和Dll)

在 Delphi 2007 DLL 和 XE6 EXE 之间传递 PChar

求教在delphi中,如何把一个exe做为res加入到dll中,并在运行时生成exe文件执行

012.Delphi插件之QPlugins,多实例内嵌窗口服务

delphi 如何把其他exe文件加入dll中,并调用

VS2017写的exe调用Delphi 7写的DLL