使用多个返回值调用DLL函数

时间:2011-07-01 08:41:52

标签: delphi dll

我的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发送数据的正确方法。

1 个答案:

答案 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;