gpt4 book ai didi

delphi - 接口(interface) DLL 表单应用程序崩溃

转载 作者:行者123 更新时间:2023-12-02 08:48:25 25 4
gpt4 key购买 nike

我的主机应用程序有问题,它加载 DLL 表单并连接某些函数和属性。

目的是加载一个dll,将名称显示为模块名称,设置与ADOTable组件的连接并显示带有数据的表单。一切正常。但关闭主机应用程序后,主机应用程序崩溃了,我得到的窗口显示 hostapp.exe 停止工作。

我不知道是通过释放库还是为接口(interface)设置nil。

你有什么解决办法吗?谢谢。

接口(interface)代码

unit u_baseplugin_intf;

interface

uses Data.Win.ADODB, Data.DB;

type
IBaseModuleInterface = interface
['{060A9C46-B3CF-4BA4-B025-2DC1D9F45076}']
function GetModuleName: Ansistring;stdcall;
procedure SetConn(sConn:TAdoConnection);stdcall;
procedure showF;stdcall;
procedure freeF;stdcall;

property ModuleName: Ansistring read GetModuleName;
property Connection : TAdoConnection write SetConn;
end;

implementation

end.

DLL代码

library profileslist;

uses
System.SysUtils,
System.Classes,
u_baseplugin_intf,
u_profileslist in 'u_profileslist.pas' {Form_DLL};

{$R *.res}

function LoadModule:IBaseModuleInterface;stdcall;
begin
result:=TForm_DLL.Create(nil);
end;

exports
LoadModule;

begin
end.

DLL 表单代码

unit u_profileslist;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.DBGrids, Vcl.StdCtrls,
u_baseplugin_intf, Data.DB,Data.Win.ADODB;

type
TForm_DLL = class(TForm, IBaseModuleInterface)
DBGrid1: TDBGrid;
ADOTable1: TADOTable;
DataSource1: TDataSource;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
{Interface methods implementation}
function GetModuleName: AnsiString;stdcall;
procedure SetConn(sConn:TAdoConnection);stdcall;
public
{ Public declarations }
{Interface methods implementation}
procedure ShowF;stdcall;
procedure FreeF;stdcall;
end;

var
Form_DLL: TForm_DLL;

implementation

{$R *.dfm}

{Interface methods implementation}
function TForm_DLL.GetModuleName;
begin
Result := 'Profiles list';
end;

procedure TForm_DLL.SetConn(sConn: TAdoConnection);
begin
AdoTable1.Connection:=sConn;
end;

procedure TForm_DLL.ShowF;
begin
ShowModal;
end;

procedure TForm_DLL.FreeF;
begin
FreeAndNil(Form_DLL);
end;

{Form_DLL methods implementation}
procedure TForm_DLL.FormClose(Sender: TObject; var Action: TCloseAction);
begin
AdoTable1.Active:=false;
end;

procedure TForm_DLL.FormShow(Sender: TObject);
begin
AdoTable1.Active:=true;
end;

end.

主机应用代码

program hostapp;

uses
Vcl.Forms,
u_hostapp in 'u_hostapp.pas' {Form1},
u_baseplugin_intf in 'u_baseplugin_intf.pas';

{$R *.res}

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

主机应用程序FORM代码

unit u_hostapp;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,

u_baseplugin_intf,
Data.Win.ADODB, Data.DB;

type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

type
TModuleInterface = function:IBaseModuleInterface; stdcall;

var
Form1: TForm1;

implementation

{$R *.dfm}
var
aModuleIntf : IBaseModuleInterface;
dllHandle : cardinal;

procedure LoadModule( aLibName : pWideChar );
var
lModule : TModuleInterface;
begin
dllHandle := LoadLibrary(aLibName) ;
if dllHandle <> 0 then
begin
@lModule := GetProcAddress(dllHandle, 'LoadModule') ;
if Assigned (lModule) then
aModuleIntf := lModule //call the function
else
begin
ShowMessage('GetModuleIntf not found.') ;
FreeLibrary(dllHandle) ;
end;
end
else
begin
ShowMessage(aLibName+' not found.') ;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
aModuleIntf.Connection:=AdoConnection1;
aModuleIntf.ShowF;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
aModuleIntf.Connection:=nil;
aModuleIntf.freeF;
aModuleIntf:=nil;
FreeLibrary(dllHandle);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
LoadModule('profileslist.dll');
Label1.Caption:=aModuleIntf.ModuleName;
end;

end.

最佳答案

您永远不会分配给Form_DLL。这意味着当您调用 FreeF 时,您将执行 FreeAndNil(Form_DLL)。由于 Form_DLLnil,因此这不会执行任何操作,并且表单仍然存在。

通过更改 LoadModule 来修复此问题:

function LoadModule:IBaseModuleInterface;stdcall;
begin
Assert(not Assigned(Form_DLL));
Form_DLL:=TForm_DLL.Create(nil);
result:=Form_DLL;
end;

尽管如此,我可能会通过完全删除 Form_DLL 来彻底改变设计。主机应用程序维护对表单的引用,可以在该表单上调用Free。换句话说,删除 Form_DLL 并实现 FreeF,如下所示:

procedure TForm_DLL.FreeF;
begin
Free; // or Destroy
end;

或者更好的是,在实现对象上使用引用计数接口(interface),并让 aModuleIntf:=nil 取下表单。

关于delphi - 接口(interface) DLL 表单应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19219650/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com