我的DLL可能会在一次拍摄中向exe发送多个结果/返回值。我仍然不明白如何制作回调函数,以便DLL可以与主机应用程序通信。
以下是该方案:
App:
type
TCheckFile = function(const Filename, var Info, Status: string): Boolean; stdcall;
var
CheckFile: TCheckFile;
DLLHandle: THandle;
Procedure Test;
var
Info,Status : string;
begin
....
// load the DLL
DLLHandle := LoadLibrary('test.dll');
if DLLHandle <> 0 then
begin
@CheckFile := GetProcAddress(DLLHandle, 'CheckFile');
if Assigned(CheckFile) then
beep
else
exit;
end;
// use the function from DLL
if Assigned(CheckFile) then
begin
if CheckFile(Filename, Info, Status) then
begin
AddtoListView(Filename, Info, Status);
end;
end;
...
end;
DLL:
function CheckFile(const Filename, var Info,Status: string): Boolean; stdcall;
var
Info, Status: string;
begin
if IsTheRightFile(Filename, Info,Status) then
begin
result := true;
exit;
end
else
begin
if IsZipFile then
begin
// call function to extract the file
ExtractZip(Filaname);
// check all extracted file
for i := 0 to ExtractedFileList.count do
begin
IsTheRightFile(ExtractedFile, Info, Status) then
// how to send the Filename, Info and Status to exe ?? // << edited
// SendIpcMessage('checkengine', pchar('◦test'), length('◦test') * SizeOf(char)); error!
// "AddtoListView(Filename, Info);" ???
end;
end;
end;
end;
实际上我仍然从上面的代码中得到错误。所以在我的情况下,我需要你的帮助来解释和确定从DLL向appp发送数据的正确方法。
答案 0 :(得分:3)
你说的是正确的,但我能看到的最明显的问题是string
变量的使用。这些是堆分配的,因为你有两个独立的内存管理器,你将在一个堆上(在DLL中)分配,然后在另一个堆上释放(在应用程序中)。
有几个选择。一种选择是共享内存管理器,但出于各种原因我不建议这样做。如果不进入它们,请在注释中声明您希望非Delphi应用程序能够使用您的DLL,这将排除使用共享内存管理器。
另一种选择是强制调用应用程序为字符串分配内存,然后让你的DLL复制到该内存中。这种方法很好,但有点劳力密集。
相反,我会使用一个字符串类型,它可以在一个模块中分配但在另一个模块中释放。 COM BSTR
就是这样一种类型,在Delphi术语中它是WideString
。更改代码以使用WideString
用于任何导出的函数。
我还会简化导入/导出过程并使用隐式动态链接。
<强> DLL 强>
function CheckFile(
const Filename: WideString;
var Info, Status: WideString
): Boolean; stdcall;
应用强>
function CheckFile(
const Filename: WideString;
var Info, Status: WideString
): Boolean; stdcall; external 'test.dll';
procedure Test(const FileName: string);
var
Info, Status: WideString;
begin
if CheckFile(Filename, Info, Status) then
AddtoListView(Filename, Info);
end;