我在Delphi中使用LoadLibrary和GetProcAddress时遇到访问冲突

时间:2015-02-19 16:52:02

标签: delphi delphi-2007

尝试使用LoadLibrary调用简单的dll时,我遇到了访问冲突:

Access violation at address 03454D62 in module 'test_dll.dll'. Write of address 00429D24.

Test.DLL代码:

library Test_DLL;

uses
  dialogs;

{$R *.res}


procedure Test(source, dest : string);stdcall;
begin
  messageDlg('Source: ' + source + chr(13) + 'Dest: ' + dest, mtInformation, [mbOk], 0);
end;

Exports
  Test;

begin
end.

使用以下方法调用该函数:

procedure TForm6.Button1Click(Sender: TObject);
type
  TCheckMessage = procedure (test1, test2 : string);
var
  CheckMessage : TCheckMessage;
  DLLHandle : Cardinal;

const
  DLL_FILE = 'test_dll.dll';
  DLL_PROC = 'Test';
begin
  dllHandle := LoadLibrary(DLL_FILE) ;
   if dllHandle <> 0 then
   begin
     @CheckMessage := GetProcAddress(dllHandle, DLL_PROC) ;
     if Assigned (CheckMessage) then
       CheckMessage('test1', 'test2')  //call the function
     else
       ShowMessage('"' + DLL_PROC + '" function not found') ;
     FreeLibrary(dllHandle) ;
   end
   else
     ShowMessage(DLL_FILE + ' not found / not loaded') ;
end;

这似乎很容易,但我必须遗漏一些东西。我注意到DLL过程调用似乎区分大小写。看起来确实发生了程序调用。 DLLHandle和@CheckMessage正在填充并且代码会运行,但是会立即引发访问冲突:

CheckMessage('test1', 'test2')

被召唤。

1 个答案:

答案 0 :(得分:2)

不允许您跨DLL边界传递string。如果使用共享内存管理器(如从库单元顶部删除的注释中所述),则可能会使用它。如果你使用完全相同版本的Delphi来编译DLL和可执行文件。

相反,您应该使用互操作安全类型。例如PAnsiCharPWideCharWideString

您的其他问题是签名不匹配。导出的函数使用stdcall调用约定。但是当您导入它时,您使用默认的register调用约定。显然,调用约定需要匹配。