这是我的一个框架程序,框架分为三部分,1.主程序(exe) 2.数据模块(dll) 3.子窗体(dll)数据模块dataunit.dll中输出一个函数,生成一个DataModule对象并返回它.
字窗体TestDLLForm.dll中输出一个函数,生成一个Form对象并返回它.
主程序引入这两个动态库函数,在OnCreate时调用它们,生成一个DataModule和Form, OnDestroy时释放这两个对象.
这个程序在不使用Run Time Package时,没有问题.但是,如果使用了Run Time Package,主程序在释放DataModule时就会报错,这是什么原因?另外,按照帮助文档:在动态库输出的函数中,如果传递的参数用到了字符串和动态数组(或是内嵌了字符串和动态数组),就应该uses sharemem. 我这里传递的参数是TObject的子类,它的很多属性都是字符串,按理需要uses sharemem,但是我没有用,也没出错,这是什么原因?动态库中用到了TXmlDocument控件时,就一定要调用 CoInitialize(nil)和 CoUninitialize.调用它们的主程序是否也需要调这两个函数?
以下是我的源程序一.主程序是一个简单的窗体,如下
//main.pasunit Main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Main, xmldom, XMLIntf, msxmldom, XMLDoc;type
TMainFrmImp = class(TForm)
XMLDocument1: TXMLDocument;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure LoadShareData;//从动态库中加载数据模块
procedure LoadChildForm;//从动态库中加载子窗体
public
{ Public declarations }
DataModule:TDataModule;
ChildForm:TForm;
end;var
MainFrmImp: TMainFrmImp;implementation
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;
stdcall;external '..\sharedata\dataunit.dll';
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;
stdcall;external '..\DllForm\TestDLLForm.dll';
{$R *.dfm}procedure TMainFrmImp.FormDestroy(Sender: TObject);
begin
if Assigned(DataModule) then
DataModule.Free;
if Assigned(ChildForm) then
ChildForm.Free;
end;procedure TMainFrmImp.FormCreate(Sender: TObject);
begin
LoadShareData;
LoadChildForm;
end;procedure TMainFrmImp.LoadChildForm;
begin
ChildForm:=CreateForm(Application.Handle,Self);
ChildForm.Show;
end;procedure TMainFrmImp.LoadShareData;
begin
DataModule:=CreateShareData(Application.Handle,Self);
end;end.这个程序在启动时从动态库中加载子窗体和数据模块,关闭时释放它们.二.数据模块 把一个DataModule放在一个动态库中,exports一个函数来生成它//sharedata.pas
unit sharedata;interfaceuses
ActiveX,SysUtils, Classes,Main,Forms, xmldom, XMLIntf, msxmldom, XMLDoc;type
TShareDataModule = class(TDataModule)
XMLDocument1: TXMLDocument;
private
{ Private declarations }
public
{ Public declarations }
MainForm:TMainFrmImp;
end;var
ShareDataModule: TShareDataModule;
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;stdcall;
implementation
{$R *.dfm}
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;
begin
Application.Handle:=AHandle;
ShareDataModule:=TShareDataModule.Create(Application); ShareDataModule.MainForm:=AOwner;
result:= ShareDataModule;
end;initialization
CoInitialize(nil);
finalization
CoUninitialize;
end.三.子窗体 把一个Form放在一个动态库中,exports一个函数来生成它unit FormUnit;interfaceuses
ActiveX,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Main, xmldom, XMLIntf, msxmldom, XMLDoc;type
TFrmTest = class(TForm)
XMLDocument1: TXMLDocument;
private
{ Private declarations }
public
{ Public declarations }
end;var
FrmTest: TFrmTest;
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;stdcall;
implementation
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;
begin
Application.Handle:=AHandle;
FrmTest:=TFrmTest.Create(Application);
result:=FrmTest;
end;
{$R *.dfm}
initialization
CoInitialize(nil);
finalization
CoUninitialize;
end.
字窗体TestDLLForm.dll中输出一个函数,生成一个Form对象并返回它.
主程序引入这两个动态库函数,在OnCreate时调用它们,生成一个DataModule和Form, OnDestroy时释放这两个对象.
这个程序在不使用Run Time Package时,没有问题.但是,如果使用了Run Time Package,主程序在释放DataModule时就会报错,这是什么原因?另外,按照帮助文档:在动态库输出的函数中,如果传递的参数用到了字符串和动态数组(或是内嵌了字符串和动态数组),就应该uses sharemem. 我这里传递的参数是TObject的子类,它的很多属性都是字符串,按理需要uses sharemem,但是我没有用,也没出错,这是什么原因?动态库中用到了TXmlDocument控件时,就一定要调用 CoInitialize(nil)和 CoUninitialize.调用它们的主程序是否也需要调这两个函数?
以下是我的源程序一.主程序是一个简单的窗体,如下
//main.pasunit Main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Main, xmldom, XMLIntf, msxmldom, XMLDoc;type
TMainFrmImp = class(TForm)
XMLDocument1: TXMLDocument;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure LoadShareData;//从动态库中加载数据模块
procedure LoadChildForm;//从动态库中加载子窗体
public
{ Public declarations }
DataModule:TDataModule;
ChildForm:TForm;
end;var
MainFrmImp: TMainFrmImp;implementation
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;
stdcall;external '..\sharedata\dataunit.dll';
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;
stdcall;external '..\DllForm\TestDLLForm.dll';
{$R *.dfm}procedure TMainFrmImp.FormDestroy(Sender: TObject);
begin
if Assigned(DataModule) then
DataModule.Free;
if Assigned(ChildForm) then
ChildForm.Free;
end;procedure TMainFrmImp.FormCreate(Sender: TObject);
begin
LoadShareData;
LoadChildForm;
end;procedure TMainFrmImp.LoadChildForm;
begin
ChildForm:=CreateForm(Application.Handle,Self);
ChildForm.Show;
end;procedure TMainFrmImp.LoadShareData;
begin
DataModule:=CreateShareData(Application.Handle,Self);
end;end.这个程序在启动时从动态库中加载子窗体和数据模块,关闭时释放它们.二.数据模块 把一个DataModule放在一个动态库中,exports一个函数来生成它//sharedata.pas
unit sharedata;interfaceuses
ActiveX,SysUtils, Classes,Main,Forms, xmldom, XMLIntf, msxmldom, XMLDoc;type
TShareDataModule = class(TDataModule)
XMLDocument1: TXMLDocument;
private
{ Private declarations }
public
{ Public declarations }
MainForm:TMainFrmImp;
end;var
ShareDataModule: TShareDataModule;
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;stdcall;
implementation
{$R *.dfm}
function CreateShareData(AHandle:THandle;AOwner:TMainFrmImp):TDataModule;
begin
Application.Handle:=AHandle;
ShareDataModule:=TShareDataModule.Create(Application); ShareDataModule.MainForm:=AOwner;
result:= ShareDataModule;
end;initialization
CoInitialize(nil);
finalization
CoUninitialize;
end.三.子窗体 把一个Form放在一个动态库中,exports一个函数来生成它unit FormUnit;interfaceuses
ActiveX,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Main, xmldom, XMLIntf, msxmldom, XMLDoc;type
TFrmTest = class(TForm)
XMLDocument1: TXMLDocument;
private
{ Private declarations }
public
{ Public declarations }
end;var
FrmTest: TFrmTest;
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;stdcall;
implementation
function CreateForm(AHandle:THandle;MainFrm:TMainFrmImp):TForm;
begin
Application.Handle:=AHandle;
FrmTest:=TFrmTest.Create(Application);
result:=FrmTest;
end;
{$R *.dfm}
initialization
CoInitialize(nil);
finalization
CoUninitialize;
end.
>>oUninitialize.调用它们的
>>主程序是否也需要调这两个函数?
主程序不用!! 因為在某個, 可能是 system 中的初始化中已經調用了!!
我以前也遇到過類似你的問題, 後來是一個同事解決的, 沒告訴我!! 我沒法給給出答案, 但我證明絕對有這個可能!!
FrmTest:=TFrmTest.Create(Application);
把Application改成主窗体,或nil,就好了.