尝试使用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')
被召唤。
答案 0 :(得分:2)
不允许您跨DLL边界传递string
。如果使用共享内存管理器(如从库单元顶部删除的注释中所述),则可能会使用它。如果你使用完全相同版本的Delphi来编译DLL和可执行文件。
相反,您应该使用互操作安全类型。例如PAnsiChar
,PWideChar
或WideString
。
您的其他问题是签名不匹配。导出的函数使用stdcall
调用约定。但是当您导入它时,您使用默认的register
调用约定。显然,调用约定需要匹配。