Delphi:在dll中调用过程后访问冲突

use*_*639 5 delphi delphi-7

我在dll中创建了一个打开表单然后打印报表的过程.这个过程完全适用于exe.我已经包含了包含此过程的单元并在dll中形成并导出过程如下:

{$R *.res}


Procedure PrintTopSellers; stdcall;
begin
  Form1 := TForm1.create(nil);
  GetMonth := TGetMonth.create(nil);
  Form1.PrintTopSellers;
end;


exports PrintTopSellers;

begin
end.
Run Code Online (Sandbox Code Playgroud)

现在我从exe调用此过程PrintTopSellers,如下所示:

procedure TForm1.Button5Click(Sender: TObject);
type
  TRead_iButton = function :integer;
var
    DLL_Handle: THandle;
    Read_iButton: TRead_iButton;
Begin
    DLL_Handle := LoadLibrary('c:\Catalog.dll');
    if DLL_Handle <> 0 then
    begin
       @Read_iButton:= GetProcAddress(DLL_Handle, 'PrintTopSellers');
        Read_iButton;
    end;
    application.ProcessMessages;
    FreeLibrary(DLL_Handle);

end;
Run Code Online (Sandbox Code Playgroud)

对程序的调用完美无缺.但是,在我关闭调用exe之后,我收到了访问冲突 - "地址00BAC89C处的访问冲突.读取地址00BAC89C".

感谢任何帮助.我正在使用Delphi 7.谢谢

Dav*_*nan 6

您正在Form1DLL 中创建一个窗口控件.但你永远不会破坏它.然后卸载DLL,卸载实现DLL创建的所有窗口的窗口过程的代码.大概是当进程关闭时,会调用窗口过程,但不再有代码了.

通过销毁DLL创建的所有对象来解决此问题.在我看来,最好的方法是在PrintTopSellers终止时这样做.

Procedure PrintTopSellers; stdcall;
begin
  Form1 := TForm1.create(nil);
  try
    GetMonth := TGetMonth.create(nil);
    try
      Form1.PrintTopSellers;
    finally
      GetMonth.Free;
    end;
  finally
    Form1.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

在加载DLL的代码中,TRead_iButton声明不正确.它应该是

TRead_iButton = procedure; stdcall;
Run Code Online (Sandbox Code Playgroud)

但这实际上并没有解释这里的问题,因为签名不匹配对于无参数过程是良性的.

  • 除非这是您第一次看到"未声明的标识符"错误,否则当您获取"应用程序"时,您已经知道该怎么做了.将`uses`子句添加到声明`Application`的单元.文档和经验都应该告诉你它是*Forms*单元. (2认同)