我现在作了一个系统,系统的框架是这样的:
主程序只负责界面显示、用户操作和服务器通信,运行时需要根据配置文件载入不同的业务模块。
业务模块负责业务逻辑的处理,通过与主程序的显示接口,显示数据。
业务模块需要向主窗体发送消息。与服务器的通讯过程:
业务模块(module)有一属性为 Connection 该属性挂接主程序的连接控件Connection
Module 发送请求数据(调用Connection的发送函数据)----〉Connection(主程序) ----〉发送服务器 ----〉处理返回结果 ----〉Connection(主程序) ---〉根据返回数据查找发送对象 ----〉返回给Module ----> Module(处理数据)
动态链接库文件library BillMeasure;uses
ShareMem,
SysUtils,
Forms,
TalentMeasure,
UBillMeasure,
Windows,
TalentFunction,
Classes;{$R *.res}var
DllApplication: TApplication;function CreateMeasure(ParentApplication: TApplication):TTalentMeasure; export; stdcall;
var Measure: TTalentBillMeasure; //用户管理
begin
Application:=ParentApplication;
Measure:=TTalentBillMeasure.Create(ParentApplication); //生成窗体
Result:=Measure;
end;procedure DLLUnloadProc(Reason: Integer); register;
begin
if Reason = DLL_PROCESS_DETACH then Application:=DllApplication;
end;
exports
CreateMeasure;begin
DllApplication:=Application;
DLLProc := @DLLUnloadProc;
end.
在主程序中调用如下:TFunctMeasure = function( ParentApplication : TApplication ) : TTalentMeasure; stdcall; //生成模块函数
TMeasureModule =Record //业务类型
Code,
Name,
FileName,
Version:string;
ICNo:integer;
Enable:boolean;
DllHandle:Cardinal;
Measure:TTalentMeasure;
end;
procedure TFrmMainWindow.LoadDll; //读入动态链接库,建立模块对象
var ii, jj: Integer;
ProcAddr: FarProc;
FunctMeasure: TFunctMeasure; //生成模块
ErrorMsg: string;
MeasureModule: TMeasureModule ;
begin with MeasureModule do
begin
DllHandle := LoadLibrary(pchar(FileName));
if DllHandle < HINSTANCE_ERROR then
begin
ErrorMsg := GetDLLError(DllHandle);
OperationLog('调用' + Name + '的动态链接库' + FileName + '出错:' + ErrorMsg);
ShowMessage(ErrorMsg);
Exit;
end
else
begin
//调用接口函数
ProcAddr := GetProcAddress(DllHandle, 'CreateMeasure');
if ProcAddr <> nil then
begin
FunctMeasure := ProcAddr;
Measure := FunctMeasure(Application); //创建计量模块对象
Measure.WinHandle:=Handle;
Measure.DataSet := TTalentDataset.Create(Application); //创建数据解析控件
Measure.DataSet.Name:='DataSet'+Code;
Measure.DataSet.Connection := TalentConnection; //链接数据链接控件
Measure.DataSet.OutTime := 30000; //请求等待时间
end;
end;
end;
以上是进行调用模块的主要过程。
调用一切正常,但是在运行时,经常会出现读内存地址错误的情况,而且会出现向主程序发送消息时会出现系统停顿。是不是通过动态链接库生成的对象,这种写法不对?
是不是在主程序在于动态链接库创建的对象进行通信时造成的错误。各位高手指教。
主程序只负责界面显示、用户操作和服务器通信,运行时需要根据配置文件载入不同的业务模块。
业务模块负责业务逻辑的处理,通过与主程序的显示接口,显示数据。
业务模块需要向主窗体发送消息。与服务器的通讯过程:
业务模块(module)有一属性为 Connection 该属性挂接主程序的连接控件Connection
Module 发送请求数据(调用Connection的发送函数据)----〉Connection(主程序) ----〉发送服务器 ----〉处理返回结果 ----〉Connection(主程序) ---〉根据返回数据查找发送对象 ----〉返回给Module ----> Module(处理数据)
动态链接库文件library BillMeasure;uses
ShareMem,
SysUtils,
Forms,
TalentMeasure,
UBillMeasure,
Windows,
TalentFunction,
Classes;{$R *.res}var
DllApplication: TApplication;function CreateMeasure(ParentApplication: TApplication):TTalentMeasure; export; stdcall;
var Measure: TTalentBillMeasure; //用户管理
begin
Application:=ParentApplication;
Measure:=TTalentBillMeasure.Create(ParentApplication); //生成窗体
Result:=Measure;
end;procedure DLLUnloadProc(Reason: Integer); register;
begin
if Reason = DLL_PROCESS_DETACH then Application:=DllApplication;
end;
exports
CreateMeasure;begin
DllApplication:=Application;
DLLProc := @DLLUnloadProc;
end.
在主程序中调用如下:TFunctMeasure = function( ParentApplication : TApplication ) : TTalentMeasure; stdcall; //生成模块函数
TMeasureModule =Record //业务类型
Code,
Name,
FileName,
Version:string;
ICNo:integer;
Enable:boolean;
DllHandle:Cardinal;
Measure:TTalentMeasure;
end;
procedure TFrmMainWindow.LoadDll; //读入动态链接库,建立模块对象
var ii, jj: Integer;
ProcAddr: FarProc;
FunctMeasure: TFunctMeasure; //生成模块
ErrorMsg: string;
MeasureModule: TMeasureModule ;
begin with MeasureModule do
begin
DllHandle := LoadLibrary(pchar(FileName));
if DllHandle < HINSTANCE_ERROR then
begin
ErrorMsg := GetDLLError(DllHandle);
OperationLog('调用' + Name + '的动态链接库' + FileName + '出错:' + ErrorMsg);
ShowMessage(ErrorMsg);
Exit;
end
else
begin
//调用接口函数
ProcAddr := GetProcAddress(DllHandle, 'CreateMeasure');
if ProcAddr <> nil then
begin
FunctMeasure := ProcAddr;
Measure := FunctMeasure(Application); //创建计量模块对象
Measure.WinHandle:=Handle;
Measure.DataSet := TTalentDataset.Create(Application); //创建数据解析控件
Measure.DataSet.Name:='DataSet'+Code;
Measure.DataSet.Connection := TalentConnection; //链接数据链接控件
Measure.DataSet.OutTime := 30000; //请求等待时间
end;
end;
end;
以上是进行调用模块的主要过程。
调用一切正常,但是在运行时,经常会出现读内存地址错误的情况,而且会出现向主程序发送消息时会出现系统停顿。是不是通过动态链接库生成的对象,这种写法不对?
是不是在主程序在于动态链接库创建的对象进行通信时造成的错误。各位高手指教。
解决方案 »
- 如何为您的安装程序进行换肤
- 在子窗体里面,添加数据记录,点提交之后,数据进入数据库,可子窗体怎么自动关闭了呢
- 如何查找一个字符串或者TString中含有多少个 : 号
- 急用!!大家帮帮忙!!!
- 消息处理:为什么在处理 WM_PAINT 消息时我去掉了 inherited 但是窗体还是能够显示?
- 用DBE连接informix,如何屏蔽用户/口令验证框
- D7中QREP的使用
- 在delphi中怎么打开readme.txt文件?
- 求助:如何将StringGrid的最左列画成宽为30,而其它列为defaultcolwidth???
- delphi的模块级异常处理如何设计?
- 熟悉李维的分布式多层应用系统篇的高手或者Socketconnect请进!
- 如何锁定DBGrid的列
解决的办法有两个:一个调用dll时,同时将application、Screen两个对象同时传递给dll,编译dll时采用动态编译的方法,发布程序时需要同时发布vcl.bpl和rtl.bpl。
另一个方法是采用bpl代替dll,这样整个程序中只有一个application,而且bpl是面向对象的,则所有问题均迎刀而解。
还有传递APPLICATION时,最好传递句柄APPLICATION.HANDLE
换尔言之,你要包装一下dll中对象的相关方法,
给主程序发消息用PostMessage