Delphi制作Dll全集(0分)

  • 主题发起人 主题发起人 阿朱
  • 开始时间 开始时间

阿朱

Unregistered / Unconfirmed
GUEST, unregistred user!
用Delphi制作DLL<br>一 Dll的制作一般步骤<br>二 参数传递<br>三 DLL的初始化和退出清理[如果需要初始化和退出清理]<br>四 全局变量的使用<br>五 调用静态载入<br>六 调用动态载入<br>七 在DLL建立一个TForM<br>八 在DLL中建立一个TMDIChildForM<br>九 示例:<br>十 Delphi制作的Dll与其他语言的混合编程中常遇问题:<br>十一 相关资料<br><br>一 Dll的制作一般分为以下几步:<br>1 在一个DLL工程里写一个过程或函数<br>2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。<br>二 参数传递<br>1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。<br>2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。<br>3 用stdcall声明后缀。<br>4 最好大小写敏感。<br>5 无须用far调用后缀,那只是为了与windows 16位程序兼容。<br><br>三 DLL的初始化和退出清理[如果需要初始化和退出清理]<br>1 DLLProc[SysUtils单元的一个Pointer]是DLL的入口。在此你可用你的函数替换了它的入口。但你的函数必须符合以下要求[其实就是一个回调函数]。如下:<br>procedure DllEnterPoint(dwReason: DWORD);far;stdcall;<br>dwReason参数有四种类型:<br>DLL_PROCESS_ATTACH:进程进入时<br>DLL_PROCESS_DETACH进程退出时<br>DLL_THREAD_ATTACH 线程进入时<br>DLL_THREAD_DETACH 线程退出时<br>在初始化部分写:<br>&nbsp; DLLProc := @DLLEnterPoint;<br>&nbsp; DllEnterPoint(DLL_PROCESS_ATTACH);<br>2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时写一句CoInitialize (nil);<br>3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。<br><br>四 全局变量的使用<br>在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。<br><br>五 调用静态载入<br>1 客户端函数声名:<br>1)大小写敏感。<br>2)与DLL中的声明一样。<br>&nbsp; &nbsp;如: showform(form:Tform);Far;external'yproject_dll.dll';<br>3)调用时传过去的参数类型最好也与windows c++一样。<br>4)调用时DLL必须在windows搜索路径中,顺序是:当前目录;Path路径;windows;widows/system;windows/ssystem32;<br><br>六 调用动态载入<br>1 建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是怎么回事了]。如:<br>type<br>&nbsp; &nbsp;mypointer=procedure(form:Tform);Far;external;<br>var<br>&nbsp; Hinst:Thandle;<br>&nbsp; showform:mypointer;<br>begin<br>&nbsp; &nbsp;Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。<br>&nbsp; showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。<br>&nbsp; showform(application.mainform);//找到函数入口指针就调用。<br>&nbsp; Freelibrary(Hinst);<br>end;<br><br>七 在DLL建立一个TForM<br>1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]<br>2 传递一个Application参数,用它建立Form.<br><br>八 在DLL中建立一个TMDIChildForM<br>1 Dll中的MDIForm.FormStyle不用为fmMDIChild.<br>2 在CreateForm后写以下两句:<br>function ShowForm(mainForm:TForm):integer;stdcall<br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; ptr:PLongInt;<br>begin<br>&nbsp; ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下<br>&nbsp; ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.<br>//为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性<br>&nbsp; Form1:=TForm1.Create(mainForm);//用参数建立<br>end;<br>备注:参数是主调程序的Application.MainForm<br><br>九 示例:<br>DLL源代码:<br>library Project2;<br><br>uses<br>&nbsp; SysUtils,<br>&nbsp; Classes,<br>&nbsp; Dialogs,<br>&nbsp; Forms,<br>&nbsp; Unit2 in 'Unit2.pas' {Form2};<br><br>{$R *.RES}<br>var<br>&nbsp; ccc: Pchar;<br><br>procedure OpenForm(mainForm:TForm);stdcall;<br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; ptr:PLongInt;<br>begin<br>&nbsp; ptr:=@(Application.MainForm);<br>&nbsp; ptr^:=LongInt(mainForm);<br>&nbsp; Form1:=TForm1.Create(mainForm);<br>end;<br><br>procedure InputCCC(Text: Pchar);stdcall;<br>begin<br>&nbsp; ccc := Text;<br>end;<br><br>procedure ShowCCC;stdcall;<br>begin<br>&nbsp; ShowMessage(String(ccc));<br>end;<br><br>exports<br>&nbsp; OpenForm;<br>&nbsp; InputCCC,<br>&nbsp; ShowCCC;<br>begin<br>end.<br><br>调用方源代码:<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Button2: TButton;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure Button2Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br>procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';<br>procedure ShowCCC;stdcall;External'project2.dll';<br>procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; Text: Pchar;<br>begin<br>&nbsp; Text := Pchar(Edit1.Text);<br>// &nbsp;OpenForm(Application.MainForm);//为了调MDICHILD<br>&nbsp; InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; ShowCCC;//这里表明WINDOWS 32位应用程序DLL中的全局变量也是在应用程序地址空间中,16位应用程序或许不同,没有做实验。<br>end;<br><br>十 Delphi制作的Dll与其他语言的混合编程中常遇问题:<br>1 与PowerBuilder混合编程<br>&nbsp; 在定义不定长动态数组方面在函数退出清理堆栈时老出现不可重现的地址错,原因未明,大概与PB的编译器原理有关,即使PB编译成二进制代码也如此。<br>
 
呵呵。楼上兄台精神可敬。
 
&nbsp;怎么不给分啊
 
To:leebons<br>你还想要分吗,知识是无价的!<br>楼上兄台精神可敬,改天我也来发表发表文章<br>:)<br>
 
好啊好啊!<br>什么时候再来个COM制作全集、控件制作全集、专家制作全集。。。(是不是太贪心了?)
 
悲酥清风同志说的这几个全集我都在考虑。不过目前我正在写一篇关于数据库存储引擎的<br>文章,改天写好给大家
 
阿朱同志,可否把全部文章发给我?谢谢。
 
期待着阿朱同志的下几个全集:)<br>P.S 我这也有个同事我们叫他阿朱的,不过他不用DELPHI的
 
真是受益非浅,我正用到这方面的东西呢。<br>多谢了。
 
只是哪个在DLL中建立一个TMDIChildForM,并动态加载这个DLL,并显示这个Form时,<br>在关闭时,要如何才能去释放这个DLL呢?<br><br>我试过,会出错的。<br>
 
我想知道怎样开发一个最简单的VCL或OCX控件。
 
真实对大富翁的高手门无私的奉贤精神,对与我正样的菜鸟真实太好。。。。。。
 
手藏收藏。。。
 
有人知道"阿朱"的信箱吗?<br>我有问题请教。<br><br>
 
<br>我在DLL写如下程序<br>function ShowForm(FHandle: THandle; mainform: TForm):LongInt;StdCall;<br>begin<br>&nbsp; ptr:=@(Application.MainForm);<br>&nbsp; ptr^:=LongInt(mainForm);<br>&nbsp; DllLongInt:=ptr^;<br>&nbsp; DllForm:=TDllForm.Create(mainform);<br>&nbsp; Result:=LongInt(DllForm);<br>end;<br><br>使用动态加载DLL见如下<br><br>procedure TMainFrm.LoadLib(LibName: String);<br>var<br>&nbsp; LibHandle &nbsp;: Thandle;<br>&nbsp; ShowForm &nbsp; : TShowForm;<br>begin<br>&nbsp; LibHandle:=LoadLibrary(LibName);<br>&nbsp; <br>&nbsp; try<br>&nbsp; &nbsp; if LibHandle=0 then raise EDLLLoadError.Create(extractfilepath(application.ExeName)+'FrmLib/'+LibName+'文件没有发现!');<br>&nbsp; &nbsp; @ShowForm:=GetProcAddress(LibHandle,'ShowForm');<br>&nbsp; &nbsp; if Assigned(ShowForm) then<br>&nbsp; &nbsp; &nbsp; ShowForm(Application.Handle, DllCortrol.Handle, MainFrm);<br>&nbsp; &nbsp;except { finally }<br>&nbsp; &nbsp; FreeLibrary(libHandle);<br>&nbsp; end;<br>end;<br><br><br>结果,我在想释放这个DLL时就出现了错误。<br><br>FreeLibrary(DllHandle);<br><br>不知如何作?<br><br>帮帮我吧
 
我的这段代码是把DLL的句柄在程序执行时换掉了,有一段再换回的代码忘写了。你在释放<br>DLL时,只要把DLL句柄换回即可。<br>DllLongInt:=ptr^;就是此意.
 
我也换回来了,可是还是一样有错误<br><br>procedure TDllForm.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br>&nbsp; Action := caFree;<br>&nbsp; ptr^:=DllLongInt;<br>end;<br><br>最好能看看你原来的代码<br>
 
前的写的次序不对,在DLL中如下写<br><br>function ShowForm(FHandle: THandle; mainform: TForm):LongInt;StdCall;<br>begin<br>&nbsp; ptr:=@(Application.MainForm);<br>&nbsp; DllLongInt:=ptr^; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//保存原句柄,多次试,发现此时为"0";<br>&nbsp; ptr^:=LongInt(mainForm); &nbsp; //修改<br>&nbsp; DllForm:=TDllForm.Create(mainform);<br>&nbsp; Result:=LongInt(DllForm);<br>end;<br><br>procedure TDllForm.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br>&nbsp; Action := caFree;<br>&nbsp; ptr^:=DllLongInt; &nbsp; &nbsp;//改为原来句柄<br>end;<br><br>可错误依旧,真不知哪里错了<br>
 
我不是在FormCreate和FormClose中写的,而是在DLL的函数中写的.那些变量也是dll的全局变量。<br>DllLongInt:=ptr^; 这两个都是.
 
后退
顶部