【发布时间】: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 时,它只会引发异常。
-
它不只是抛出异常。它抛出带有消息的特定类的异常。您没有告诉我们该信息的事实表明您忽略了它。不。学会理解它。并始终包含该信息。