调用DLL问题,已经没辙了,请大家帮忙 ( 积分: 80 )

  • 主题发起人 主题发起人 skyroom007
  • 开始时间 开始时间
S

skyroom007

Unregistered / Unconfirmed
GUEST, unregistred user!
写了一个主程序,调用各个功能模块,一个EXE调用多个DLL<br>采用BDE连接,主FORM建立一个永久性的DATABASE连接,<br>采用数据库别名的方式,每个DLL中的TQUERY都连接这个别名<br>主FORM的程序如下<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;FDLLProcList&nbsp;:TDLLProcList;<br><br>&nbsp;&nbsp;public<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Public&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;lpData:PNotifyIconData;<br>&nbsp;&nbsp;&nbsp;&nbsp;unm:shortstring;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//员工代码<br>&nbsp;&nbsp;&nbsp;&nbsp;bmm:shortstring;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//部门代码<br>&nbsp;&nbsp;&nbsp;&nbsp;gsm:shortstring;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//公司代码<br>&nbsp;&nbsp;&nbsp;&nbsp;qx:shortstring;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;ShowDLL(str:string);<br>&nbsp;&nbsp;end;<br><br>var<br>&nbsp;&nbsp;MainForm:&nbsp;TMainForm;<br><br>implementation<br><br>{$R&nbsp;*.dfm}<br>procedure&nbsp;TMainForm.FormCreate(Sender:&nbsp;TObject);<br>begin<br>&nbsp;FDLLProcList:=TDLLProcList.Create;<br>&nbsp;LoginForm:=TFormLogin.Create(self);<br>end;<br><br>procedure&nbsp;TMainForm.FormDestroy(Sender:&nbsp;TObject);<br>begin<br>FDLLProcList.Free;<br>end;<br><br>procedure&nbsp;TMainForm.ShowDLL(str:string);<br>var&nbsp;PP:myproc;<br>begin<br>&nbsp;if&nbsp;FDLLProcList.LoadModule(str,'Load')&nbsp;then<br>&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;FDLLProcList.RunModule(str,'Load')(Application,Sessions,nil,unm,bmm,gsm,qx);<br>&nbsp;end&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application.MessageBox(Pchar('应用模块&nbsp;:&nbsp;'+str+'&nbsp;不存在!'),&nbsp;Pchar(Caption),&nbsp;<br><br>MB_OK+MB_ICONEXCLAMATION+MB_DEFBUTTON1+MB_APPLMODAL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>end;<br><br>procedure&nbsp;TMainForm.N11Click(Sender:&nbsp;TObject);<br>begin<br>MainForm.ShowDLL('dqdpr');<br>end;<br>end.<br><br>TDLLProcList&nbsp;为一个公用单元&nbsp;UNITDLL&nbsp;<br>代码如下<br>unit&nbsp;UnitDLL;<br>interface<br>uses&nbsp;Classes,&nbsp;&nbsp;Windows,&nbsp;Messages,&nbsp;SysUtils,&nbsp;Graphics,&nbsp;Controls,&nbsp;Forms,&nbsp;Dialogs,DBTables,&nbsp;StdCtrls,Menus;<br>&nbsp;Type<br>&nbsp;&nbsp;&nbsp;MyProc=procedure&nbsp;(myHandle:Tapplication;Session1:TsessionList;MenuI:TMenuItem;unm,bmm,gsm,qx:ShortString);<br>&nbsp;&nbsp;&nbsp;TDLLProcList=class(TStringList)<br>&nbsp;&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;FDLLList&nbsp;:TList;<br>&nbsp;&nbsp;&nbsp;FProcList&nbsp;:TList;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;FIndex&nbsp;:Integer;<br>&nbsp;&nbsp;&nbsp;FProc&nbsp;:MyProc;<br>&nbsp;&nbsp;&nbsp;public<br>&nbsp;&nbsp;&nbsp;constructor&nbsp;Create&nbsp;;<br>&nbsp;&nbsp;&nbsp;destructor&nbsp;Destroy&nbsp;;&nbsp;override;<br>&nbsp;&nbsp;&nbsp;function&nbsp;RunModule(ModuleName,ProcName&nbsp;:String):&nbsp;MyProc;<br>&nbsp;&nbsp;&nbsp;function&nbsp;GetModule:&nbsp;MyProc;<br>&nbsp;&nbsp;&nbsp;function&nbsp;LoadModule(ModuleName,ProcName&nbsp;:String):boolean;<br>&nbsp;&nbsp;&nbsp;end;<br>implementation<br>&nbsp;&nbsp;&nbsp;Type<br>&nbsp;&nbsp;&nbsp;PHandle&nbsp;=^THandle;<br>&nbsp;&nbsp;&nbsp;PMyProc&nbsp;=^MyProc;<br>&nbsp;&nbsp;&nbsp;constructor&nbsp;TDLLProcList.Create;<br>&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;FDLLList:=TList.Create;<br>&nbsp;&nbsp;&nbsp;FProcList:=TList.Create;<br>&nbsp;&nbsp;&nbsp;inherited&nbsp;Create;<br>&nbsp;&nbsp;&nbsp;end;<br>destructor&nbsp;TDLLProcList.Destroy;<br>&nbsp;&nbsp;&nbsp;var&nbsp;i:integer;<br>&nbsp;&nbsp;&nbsp;mhandle:PHandle&nbsp;;<br>&nbsp;&nbsp;&nbsp;ppMyProc:PMyProc;<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;inherited&nbsp;Destroy;<br>&nbsp;&nbsp;for&nbsp;i:=0&nbsp;to&nbsp;FProcList.Count-1&nbsp;do&nbsp;begin<br>&nbsp;&nbsp;ppMyProc:=FProcList.items;<br>&nbsp;&nbsp;FreeMem(ppMyProc);<br>&nbsp;end;<br>&nbsp;&nbsp;for&nbsp;i:=0&nbsp;to&nbsp;FDLLList.Count-1&nbsp;do&nbsp;begin<br>&nbsp;&nbsp;&nbsp;mhandle:=FDLLList.items;<br>&nbsp;&nbsp;&nbsp;freelibrary(mhandle^);&nbsp;&nbsp;freeMem(mhandle);<br>&nbsp;end;<br>&nbsp;FDLLList.Free;<br>&nbsp;FProcList.Free;<br>&nbsp;end;<br><br>function&nbsp;TDLLProcList.RunModule(ModuleName,ProcName&nbsp;:String):&nbsp;MyProc;<br>&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;result:=nil;<br>&nbsp;&nbsp;&nbsp;if&nbsp;LoadModule(ModuleName,ProcName)&nbsp;then&nbsp;begin<br>&nbsp;&nbsp;&nbsp;GetModule;<br>&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;:=FProc;<br>&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;end;<br><br>function&nbsp;TDLLProcList.LoadModule(ModuleName,ProcName&nbsp;:String):boolean;<br>&nbsp;&nbsp;&nbsp;var&nbsp;i:integer;<br>&nbsp;&nbsp;&nbsp;&nbsp;mhandle:PHandle&nbsp;;<br>&nbsp;&nbsp;&nbsp;&nbsp;ppMyProc:PMyProc;<br>&nbsp;&nbsp;&nbsp;&nbsp;mMyProc&nbsp;:MyProc;<br>&nbsp;&nbsp;&nbsp;&nbsp;mdllname,mp:String;<br>&nbsp;&nbsp;&nbsp;&nbsp;mTHandle:THandle;<br>&nbsp;begin<br>&nbsp;result:=false;<br>&nbsp;&nbsp;i:=IndexOf(ModuleName+':'+ProcName);<br>&nbsp;&nbsp;if&nbsp;i&gt;-1&nbsp;then&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;FIndex&nbsp;:=&nbsp;i;&nbsp;&nbsp;&nbsp;Result:=True;<br>&nbsp;&nbsp;end&nbsp;else&nbsp;begin<br>&nbsp;&nbsp;mdllname:=Copy(ModuleName,1,length(ModuleName))+'.dll';<br>&nbsp;&nbsp;mTHandle:=LoadLibrary(pchar(mdllname));<br>&nbsp;&nbsp;mp:=&nbsp;Copy(procname,1,length(ProcName));<br>&nbsp;&nbsp;if&nbsp;mThandle&lt;&gt;0&nbsp;then&nbsp;begin<br>&nbsp;&nbsp;&nbsp;@mMyProc:=GetProcAddress(mTHandle,pchar(mp));<br>&nbsp;&nbsp;&nbsp;if&nbsp;@mMyProc&lt;&gt;&nbsp;nil&nbsp;then&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;New(ppMyProc);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ppMyProc^:=mMyProc;&nbsp;FProcList.Add(ppMyProc);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;New(mHandle);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mHandle^:=mTHandle;&nbsp;FIndex:=FDllList.Add(mHandle);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add(ModuleName+':'+ProcName);&nbsp;&nbsp;&nbsp;&nbsp;Result:=True;<br>&nbsp;&nbsp;&nbsp;end&nbsp;else&nbsp;Exception.Create('以下调用函数不存在&nbsp;'+ModuleName+':'+ProcName);<br>&nbsp;&nbsp;end&nbsp;else&nbsp;Exception.Create('以下模块不存在&nbsp;'+ModuleName+':'+ProcName);<br>&nbsp;end;<br>end;<br><br>function&nbsp;TDLLProcList.GetModule:MyProc;<br>var&nbsp;&nbsp;&nbsp;ppMyProc:PMyProc;<br>&nbsp;begin<br>&nbsp;&nbsp;ppMyProc&nbsp;:=&nbsp;FProcList.Items[FIndex];<br>&nbsp;&nbsp;FProc:=ppMyProc^;<br>&nbsp;&nbsp;Result&nbsp;:=ppMyProc^;<br>&nbsp;end;<br>end.<br><br>调用的DLL的程序如下<br>library&nbsp;dqdpr;<br><br>{&nbsp;Important&nbsp;note&nbsp;about&nbsp;DLL&nbsp;memory&nbsp;management:&nbsp;ShareMem&nbsp;must&nbsp;be&nbsp;the<br>&nbsp;&nbsp;first&nbsp;unit&nbsp;in&nbsp;your&nbsp;library's&nbsp;USES&nbsp;clause&nbsp;AND&nbsp;your&nbsp;project's&nbsp;(select<br>&nbsp;&nbsp;Project-View&nbsp;Source)&nbsp;USES&nbsp;clause&nbsp;if&nbsp;your&nbsp;DLL&nbsp;exports&nbsp;any&nbsp;procedures&nbsp;or<br>&nbsp;&nbsp;functions&nbsp;that&nbsp;pass&nbsp;strings&nbsp;as&nbsp;parameters&nbsp;or&nbsp;function&nbsp;results.&nbsp;This<br>&nbsp;&nbsp;applies&nbsp;to&nbsp;all&nbsp;strings&nbsp;passed&nbsp;to&nbsp;and&nbsp;from&nbsp;your&nbsp;DLL--even&nbsp;those&nbsp;that<br>&nbsp;&nbsp;are&nbsp;nested&nbsp;in&nbsp;records&nbsp;and&nbsp;classes.&nbsp;ShareMem&nbsp;is&nbsp;the&nbsp;interface&nbsp;unit&nbsp;to<br>&nbsp;&nbsp;the&nbsp;BORLNDMM.DLL&nbsp;shared&nbsp;memory&nbsp;manager,&nbsp;which&nbsp;must&nbsp;be&nbsp;deployed&nbsp;along<br>&nbsp;&nbsp;with&nbsp;your&nbsp;DLL.&nbsp;To&nbsp;avoid&nbsp;using&nbsp;BORLNDMM.DLL,&nbsp;pass&nbsp;string&nbsp;information<br>&nbsp;&nbsp;using&nbsp;PChar&nbsp;or&nbsp;ShortString&nbsp;parameters.&nbsp;}<br><br>uses<br>&nbsp;&nbsp;SysUtils,<br>&nbsp;&nbsp;Classes,<br>&nbsp;&nbsp;DQpas&nbsp;in&nbsp;'DQpas.pas'&nbsp;{CKDQ};<br><br>{$R&nbsp;*.res}<br>exports<br>&nbsp;Load&nbsp;name&nbsp;'Load';<br>begin<br>end.<br><br>DLL有一个FORM&nbsp;有Tquery控件连接BDE别名<br>代码如下<br>unit&nbsp;DQpas;<br><br>interface<br><br>uses<br>&nbsp;&nbsp;Windows,&nbsp;Messages,&nbsp;SysUtils,&nbsp;Classes,&nbsp;Graphics,&nbsp;Controls,&nbsp;Forms,&nbsp;Dialogs,<br>&nbsp;&nbsp;Db,&nbsp;DBTables,&nbsp;ImgList,&nbsp;ComCtrls,&nbsp;StdCtrls,&nbsp;ExtCtrls,Menus,&nbsp;DBCtrls,<br>&nbsp;&nbsp;Grids,&nbsp;DBGrids,&nbsp;Buttons,&nbsp;DBSBtn;<br><br>type<br>&nbsp;&nbsp;TCKDQ&nbsp;=&nbsp;class(TForm)<br>&nbsp;&nbsp;&nbsp;&nbsp;DBGrid1:&nbsp;TDBGrid;<br>&nbsp;&nbsp;&nbsp;&nbsp;qry_main:&nbsp;TQuery;<br>&nbsp;&nbsp;&nbsp;&nbsp;DataSource1:&nbsp;TDataSource;<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;public<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Public&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MenuItem:TMenuItem;<br>&nbsp;&nbsp;end;<br>procedure&nbsp;Load(App:TApplication;Sessions1:TSessionList;MenuI:TmenuItem;unm1,bmm1,gsm1,qx1:shortstring);export;<br><br>var<br>&nbsp;&nbsp;CKDQ:&nbsp;TCKDQ;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unm:shortstring;<br><br>implementation<br><br>{$R&nbsp;*.dfm}<br>procedure&nbsp;Load(App:TApplication;Sessions1:TSessionList;MenuI:TmenuItem;unm1,bmm1,gsm1,qx1:shortstring);export;<br>begin<br>&nbsp;unm:=unm1;<br>&nbsp;Application:=App;<br>&nbsp;Sessions:=Sessions1;<br>&nbsp;with&nbsp;TCKDQ.Create(Application)&nbsp;do&nbsp;begin<br>&nbsp;&nbsp;MenuItem:=MenuI;<br>&nbsp;show;<br>&nbsp;end;<br>end;<br><br>end.<br><br>问题是&nbsp;如果Tquery空间中没有写任何语句&nbsp;主程序能调用成功如果写了语句就无法调用了出现如下报错<br>Exception&nbsp;EdatabaseError&nbsp;in&nbsp;module&nbsp;dqdpr.dll&nbsp;at&nbsp;000715FD<br><br>请教如何解决?&nbsp;谢谢
 
DLL生成的时候,Delphi自动写的这段英文兄弟没看?<br>{&nbsp;Important&nbsp;note&nbsp;about&nbsp;DLL&nbsp;memory&nbsp;management:&nbsp;ShareMem&nbsp;must&nbsp;be&nbsp;the<br>&nbsp;&nbsp;first&nbsp;unit&nbsp;in&nbsp;your&nbsp;library's&nbsp;USES&nbsp;clause&nbsp;AND&nbsp;your&nbsp;project's&nbsp;(select<br>&nbsp;&nbsp;Project-View&nbsp;Source)&nbsp;USES&nbsp;clause&nbsp;if&nbsp;your&nbsp;DLL&nbsp;exports&nbsp;any&nbsp;procedures&nbsp;or<br>&nbsp;&nbsp;functions&nbsp;that&nbsp;pass&nbsp;strings&nbsp;as&nbsp;parameters&nbsp;or&nbsp;function&nbsp;results.&nbsp;This<br>&nbsp;&nbsp;applies&nbsp;to&nbsp;all&nbsp;strings&nbsp;passed&nbsp;to&nbsp;and&nbsp;from&nbsp;your&nbsp;DLL--even&nbsp;those&nbsp;that<br>&nbsp;&nbsp;are&nbsp;nested&nbsp;in&nbsp;records&nbsp;and&nbsp;classes.&nbsp;ShareMem&nbsp;is&nbsp;the&nbsp;interface&nbsp;unit&nbsp;to<br>&nbsp;&nbsp;the&nbsp;BORLNDMM.DLL&nbsp;shared&nbsp;memory&nbsp;manager,&nbsp;which&nbsp;must&nbsp;be&nbsp;deployed&nbsp;along<br>&nbsp;&nbsp;with&nbsp;your&nbsp;DLL.&nbsp;To&nbsp;avoid&nbsp;using&nbsp;BORLNDMM.DLL,&nbsp;pass&nbsp;string&nbsp;information<br>&nbsp;&nbsp;using&nbsp;PChar&nbsp;or&nbsp;ShortString&nbsp;parameters.&nbsp;}<br>已经告诉你注意事项了,请按照这段英文操作就可以了.<br>英文大意是,关于dll中内存管理器的问题,如果你的dll中函数的参数或者返回值的类型(如果类型是类对象的话,包含类对象中的属性)是string类型的话,请在dll和exe的dpr文件的uses语句第一行引用ShareMem.引用ShareMem后,程序分发的时候需要分发Borlndmm.dll这个dll文件.如果你想避免这样&nbsp;,请不要在dll的函数的参数和返回值中返回string类型(包括任何有string类型的类对象),而是改用PChar或者ShortString来代替.
 
怎么改呢?不好意思&nbsp;我也是没怎么接触过DLL编程.
 
library&nbsp;dqdpr;<br><br>{&nbsp;Important&nbsp;note&nbsp;about&nbsp;DLL&nbsp;memory&nbsp;management:&nbsp;ShareMem&nbsp;must&nbsp;be&nbsp;the<br>&nbsp;&nbsp;first&nbsp;unit&nbsp;in&nbsp;your&nbsp;library's&nbsp;USES&nbsp;clause&nbsp;AND&nbsp;your&nbsp;project's&nbsp;(select<br>&nbsp;&nbsp;Project-View&nbsp;Source)&nbsp;USES&nbsp;clause&nbsp;if&nbsp;your&nbsp;DLL&nbsp;exports&nbsp;any&nbsp;procedures&nbsp;or<br>&nbsp;&nbsp;functions&nbsp;that&nbsp;pass&nbsp;strings&nbsp;as&nbsp;parameters&nbsp;or&nbsp;function&nbsp;results.&nbsp;This<br>&nbsp;&nbsp;applies&nbsp;to&nbsp;all&nbsp;strings&nbsp;passed&nbsp;to&nbsp;and&nbsp;from&nbsp;your&nbsp;DLL--even&nbsp;those&nbsp;that<br>&nbsp;&nbsp;are&nbsp;nested&nbsp;in&nbsp;records&nbsp;and&nbsp;classes.&nbsp;ShareMem&nbsp;is&nbsp;the&nbsp;interface&nbsp;unit&nbsp;to<br>&nbsp;&nbsp;the&nbsp;BORLNDMM.DLL&nbsp;shared&nbsp;memory&nbsp;manager,&nbsp;which&nbsp;must&nbsp;be&nbsp;deployed&nbsp;along<br>&nbsp;&nbsp;with&nbsp;your&nbsp;DLL.&nbsp;To&nbsp;avoid&nbsp;using&nbsp;BORLNDMM.DLL,&nbsp;pass&nbsp;string&nbsp;information<br>&nbsp;&nbsp;using&nbsp;PChar&nbsp;or&nbsp;ShortString&nbsp;parameters.&nbsp;}<br><br>uses<br>&nbsp;&nbsp;[red]ShareMem[/red],<br>&nbsp;&nbsp;SysUtils,<br>&nbsp;&nbsp;Classes,<br>&nbsp;&nbsp;DQpas&nbsp;in&nbsp;'DQpas.pas'&nbsp;{CKDQ};<br><br>打开你的dll的dpr文件(如上)增加红色的那部分.然后打开你的exe的dpr文件,同样增加这个部分.然后重新编译dll和exe(注意,必须全部重新编译一边)就ok了
 
加了&nbsp;然后跟踪了一下&nbsp;在<br>procedure&nbsp;TMainForm.ShowDLL(str:string);<br>var&nbsp;PP:myproc;<br>begin<br>&nbsp;if&nbsp;FDLLP<br><br><br><br><br>rocList.LoadModule(str,'Load')&nbsp;then<br>&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;FDLLProcList.RunModule(str,'Load')(Application,Sessions,nil,unm,bmm,gsm,qx);<br>&nbsp;end&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application.MessageBox(Pchar('应用模块&nbsp;:&nbsp;'+str+'&nbsp;不存在!'),&nbsp;Pchar(Caption),&nbsp;<br><br>MB_OK+MB_ICONEXCLAMATION+MB_DEFBUTTON1+MB_APPLMODAL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>end;<br>报错内容为&nbsp;Project&nbsp;AKSoftApp.exe&nbsp;raised&nbsp;exception&nbsp;class&nbsp;EDataBaseError&nbsp;with&nbsp;message'Duplicate&nbsp;database&nbsp;name&nbsp;'AKTMIS''&nbsp;.Process&nbsp;stopped&nbsp;use&nbsp;step&nbsp;or&nbsp;run&nbsp;to&nbsp;continue&nbsp;//AKTMIS为数据库别名<br>继续执行报如下错误<br>//Execption&nbsp;Edbast<br>Exception&nbsp;EdatabaseError&nbsp;in&nbsp;module&nbsp;dqdpr.dll&nbsp;at&nbsp;00071761
 
dll不要与主程序共享一个数据库连接,它是一个单独的模块。<br>要有自己的连接。
 
dll共享主程序的数据连结没有任何问题,只不过在装入dll或者dll的初始化部分,一定要<br>将相关控件传给它,这样dll的窗体使用起来跟同一个exe内的窗体差不多。
 
多人接受答案了。
 
后退
顶部