如何正确地动态调用DLL

时间:2018-12-18 10:19:38

标签: delphi

我尝试按照本教程link进行操作,但是由于 FreeLibary 导致其始终抛出访问冲突错误。我哪里做错了?这是我的DLL代码:

library EditDocument;

uses
  System.SysUtils,
  Vcl.Dialogs,
  System.Classes,
  dxmdaset;

{$R *.res}



procedure EditDocument2(const fieldName : string); stdcall;
begin
  ShowMessage(fieldName);
end;


exports EditDocument2;

begin
end.

这就是我在主程序中调用它的方式:

procedure TfrmMain.btn1Click(Sender: TObject);
type
  TDLL_EditDocument = procedure (const fieldName : string); stdcall;

var
  dllHandle : THandle;
  aFunction : TDLL_EditDocument;
begin

  dllHandle := LoadLibrary('EditDocument.dll') ;

  if dllHandle = 0 then
  begin
    CommonHelper.MsgDlgError('DLL not found EditDocument.dll');
    Exit;
  end;

  @aFunction := GetProcAddress(dllHandle, 'EditDocument2') ;
  if Assigned (aFunction) then
  begin
    aFunction('test');
  end;

  FreeLibrary(dllHandle);


end;

此外,我在主项目中使用了 Sharemem ,它是uses子句中的第一个单元。我尝试将stdcall更改为cdecl,将参数更改为shortstring,甚至删除了所有参数,但在FreeLibrary期间始终抛出错误。我敢肯定这很简单,但是已经花了我2个小时。 我正在使用Delphi XE7。 预先感谢

2 个答案:

答案 0 :(得分:2)

如果要使用Sharemem,则还需要在DLL项目中使用它。 DLL项目的use子句中缺少它。

除该错误外,最有可能引起您的错误的怀疑是您使用的单元之一的完成代码。已知RTL和VCL单元可以处理动态加载和卸载,这将手指指向dxmdaset。尝试从DLL中删除该单元。

最后,有时外部DLL会引发在调试器中触发的首次机会异常,但实际上不会引起任何问题。您是否已100%确定对FreeLibrary的呼叫实际上并未成功返回。您可以通过捕获并输出FreeLibrary的返回值来做到这一点。

答案 1 :(得分:1)

使用Sharemem时,它必须是主项目库中的第一个单元。

当删除所有不应该成为问题的参数时(另请参见Sharemem, when is it not needed),但是尝试时可能没有编译两个项目。当您仅点击编译/运行,甚至编译时,只会编译当前项目。玩转过程签名时,请确保运行Project-> Build All。