找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 3938|回复: 0

【分享】Delphi创建DLL动态链接库

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2009-7-26 14:21:55 | 显示全部楼层 |阅读模式
<p>Windows 的执行文件可以划分为两种形式程序和动态连接库(DLLs)。一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL 中的函数。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 当我们调用Windows 中的API 函数的时候,实际上就是调用存储在DLL 中的函数。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 在如下几种情况下,调用DLL 是合理的:<br/>&nbsp;&nbsp;&nbsp;&nbsp; 1) 不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 2) 当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 3) 由于DLL 是独立于语言的,所以,当不同语言习惯的人共同开发一个大型项目的时候,使用DLL 便于程序系统的交流,当然,Delphi开发的DLL 也可以在诸如Visual BASIC,C++ 等系统中使用。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 下面通过几个例子,说明Delphi开发动态连接库的方法和规范。&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 第一节 动态连接库的构建和调用方法</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 一、动态连接库构建<br/>&nbsp;&nbsp;&nbsp;&nbsp; File---New---Other---DLL Wizard<br/>&nbsp;&nbsp;&nbsp;&nbsp; 这就创建了一个动态连接库的基本模块<br/>&nbsp;&nbsp;&nbsp;&nbsp; library Project2;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uses<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SysUtils,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Classes;<br/>&nbsp;&nbsp; {$R *.res}<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; end.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 把工程名改为Mydll,并写入必要的函数</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; library mydll;<br/>&nbsp;&nbsp;&nbsp;&nbsp; uses<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SysUtils,Classes,Dialogs,windows;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; function Triple(N:Integer):integer;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result:=N+3;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; function Double(N:Integer):integer;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result:=N+2;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; function Triple1(N:Integer):integer;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; showmessage('计算N+3');<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result:=N+3;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; function Double1(N:Integer):integer;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; messagebox(0,'计算N+2','计算N+2',mb_ok);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result:=N+2;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp; exports<br/>&nbsp;&nbsp;&nbsp;&nbsp; Triple name 'Tr',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Double name 'Do',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Triple1 name 'TrM',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Double1 name 'DoM';</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; Triple,Double,Triple1,Double1;</p>
<p>&nbsp;&nbsp; {$R *.RES}</p>
<p>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp; end.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 其中函数:Triple:把传入值加三<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Double:把传入值加二<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Triple1:把传入值加三并显示提示<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Double1:把传入值加二并显示提示</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 从这个例子中可以看出DLL 程序的几个规则:<br/>&nbsp;&nbsp;&nbsp;&nbsp; 1) 在DLL 程序中,输出函数必须被声明为stdcall,以使用标准的Win32 参数传递技术来代替优化的Register。(说明:在Delphi中Register方式是缺省的调用约定,这个约定尽量采用寄存器来传递参数,传递次序从左到右,最多可用到3个CPU 的寄存器,如果参数多于3 个,剩下的就通过栈来传送,使用寄存器传送可保证参数传递的速度最快。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 而stdcall 方式是通过Windows 的标准调用来传递参数,传递秩序从左到右,这种方式适合调用Windows 的API ,在DLL 中,当然要使用这种方式)。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 2)所有的输出函数都必须列在exports子句下面,这使的子例程在DLL外部就可以看到。</p>
<p>&nbsp;&nbsp; exports<br/>&nbsp;&nbsp;&nbsp;&nbsp; Triple name 'Tr',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Double name 'Do',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Triple1 name 'TrM',<br/>&nbsp;&nbsp;&nbsp;&nbsp; Double1 name 'DoM';<br/>&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp; 列出了用户使用这个函数的接口名字。虽然别名不是必须的,但最好给个别名,以便用户程序更容易找到这个函数,同时还要指出,Delphi 6.0取消了Delphi 5.0中允许使用的index ,如果还用Index来指明接口名字,Delphi 6.0中将提示错误。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 实例中给出了两种提示方法,主要想说明一个问题:<br/>&nbsp;&nbsp;&nbsp;&nbsp; showmessage(''),是VCL 提供的函数,由于多次编译VCL,做出的程序会比较大。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 而messagebox(0,'','',mb_ok)&nbsp;&nbsp; 是Windows提供的API 函数,做出的程序会比较小。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 这就是说,编写DLL 程序的时候,要尽量避免多次编译VCL 。作为一个实例,这里把两种方法都列出来了。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 保存<br/>&nbsp;&nbsp;&nbsp;&nbsp; 编译:Projrct---Build Mydll<br/>&nbsp;&nbsp;&nbsp;&nbsp; 这就完成了一个简单的动态连接库的编写。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 二、动态连接库的调用<br/>&nbsp;&nbsp;&nbsp;&nbsp; 首先在implementation下做调用声明</p>
<p>const<br/>&nbsp;&nbsp; gdi32='mydll.dll';<br/>function triple(n:integer):integer;stdcall;external gdi32 name 'Tr';<br/>function Double(N:Integer):integer;stdcall;external gdi32 name 'Do';<br/>function triple1(n:integer):integer;stdcall;external gdi32 name 'TrM';<br/>function Double1(N:Integer):integer;stdcall;external gdi32 name 'DoM';</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 以后程序中就可以作为普通的函数使用了,例如:</p>
<p>procedure TForm1.Button1Click(Sender: TObject);<br/>var N:integer;<br/>begin<br/>&nbsp;&nbsp; N:=updown1.position;<br/>&nbsp;&nbsp; edit1.text:=inttostr(triple(N));<br/>end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 第二节 DLL 中的Delphi窗体<br/>&nbsp;&nbsp;&nbsp;&nbsp; 一、在DLL 中放置窗的的方法<br/>&nbsp;&nbsp;&nbsp;&nbsp; 在DLL 中,除了放置标准的函数和过程以外,也可以放置已经做好的的delphi窗体,也可以把做好的窗体供其它程序使用,方法是:<br/>&nbsp;&nbsp; 1)首先按普通方法制作窗体,不过在interface区域,对接口函数做如下声明<br/>&nbsp;&nbsp; function Createform(capt:string):string;stdcall;<br/>&nbsp;&nbsp; 2)在implementation下加入接口函数<br/>function Createform(capt:string):string;stdcall;<br/>var&nbsp;&nbsp; Form1: TForm1;<br/>begin<br/>&nbsp;&nbsp; form1:=Tform1.Create(application);<br/>&nbsp;&nbsp; form1.show;<br/>&nbsp;&nbsp; form1.caption:=capt;<br/>end;</p>
<p>&nbsp;&nbsp; 3)制作DLL 动态连接库,但要声明:<br/>uses<br/>&nbsp;&nbsp; unit1 in 'unit1.pas';<br/>exports<br/>{写入接口标示符}<br/>Createform name 'Myform';</p>
<p>&nbsp;&nbsp; 4)调用窗体的程序按普通方法制作,但是 在implementation下首先声明要调用的DLL函数<br/>const<br/>&nbsp;&nbsp; gdi32='myFormdll.dll';<br/>&nbsp;&nbsp; function Createform(capt:string):string;stdcall;external gdi32 name 'Myform';</p>
<p>procedure TForm3.Button1Click(Sender: TObject);<br/>var n,m:string;<br/>begin<br/>&nbsp;&nbsp; m:='我的窗体';<br/>&nbsp;&nbsp; Createform(m);var n,m:string;<br/>end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 二、DLL 中的调用窗体时的数据传递<br/>&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp; 在窗体调用时,可以用普通的函数方法传递数据,下面举个例子。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 1)建立窗体<br/>&nbsp;&nbsp;&nbsp;&nbsp; 做一个改变颜色窗体,放在DLL 中,可以用普通的方法来做,但要作如下声明:<br/>&nbsp;&nbsp;&nbsp;&nbsp; function mycolor(col:longint):longint;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; function Getcolor:longint;stdcall;<br/>&nbsp;&nbsp;&nbsp;&nbsp; 其中,mycolor为构造窗体;Getcolor为传递颜色数据。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 在implementation区声明一个窗体内全局的变量<br/>&nbsp;&nbsp;&nbsp;&nbsp; var color1:longint;<br/>&nbsp;&nbsp;&nbsp;&nbsp; 下面写出相应的程序</p>
<p>function mycolor(col:longint):longint;stdcall;<br/>var&nbsp;&nbsp; Form1: TForm1;<br/>begin<br/>&nbsp;&nbsp; form1:=Tform1.Create(application);<br/>&nbsp;&nbsp; form1.show;<br/>&nbsp;&nbsp; form1.panel1.Color:=col;<br/>&nbsp;&nbsp; form1.edit1.Text:=inttostr(form1.panel1.Color);<br/>&nbsp;&nbsp; result:=color1;<br/>end;</p>
<p>function Getcolor:longint;stdcall;<br/>begin<br/>&nbsp;&nbsp; result:=color1;<br/>end;</p>
<p>procedure TForm1.ScrollBar1Change(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; panel2.Color:=RGB(ScrollBar1.Position,ScrollBar2.Position,ScrollBar3.Position);<br/>&nbsp;&nbsp; edit2.Text:=inttostr(panel2.Color);<br/>&nbsp;&nbsp; color1:=panel2.Color;<br/>end;</p>
<p>procedure TForm1.Button2Click(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; Free;&nbsp;&nbsp; //析构Form1<br/>end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 2)建立动态连接库<br/>&nbsp;&nbsp;&nbsp;&nbsp; 运行成功后,再建立动态连接库:<br/>library FormDLL;</p>
<p>{从文件调入}<br/>uses<br/>&nbsp;&nbsp; unit1 in 'unit1.pas';<br/>exports</p>
<p>{写入接口标示符}<br/>Mycolor name 'My',<br/>Getcolor name 'Get';</p>
<p>begin<br/>end.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 3)建立调用的程序<br/>&nbsp;&nbsp;&nbsp;&nbsp; 首先声明要调用的DLL函数</p>
<p>const<br/>&nbsp;&nbsp; gdi32='formDll.dll';<br/>&nbsp;&nbsp; function Mycolor(col:longint):longint;stdcall;external gdi32 name 'My';<br/>&nbsp;&nbsp; function Getcolor:longint;stdcall;external gdi32 name 'Get';</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 然后写出相应的程序</p>
<p>procedure TForm1.Button1Click(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; Mycolor(color);<br/>end;</p>
<p>procedure TForm1.Button2Click(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; color:=getcolor;<br/>end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 我们可以看到,在改变颜色的窗体中做了颜色变化后,当前窗体的颜色将发生变化。</p>
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表