手把手教delphi写你的dll文件_第1页
手把手教delphi写你的dll文件_第2页
手把手教delphi写你的dll文件_第3页
手把手教delphi写你的dll文件_第4页
手把手教delphi写你的dll文件_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、手把手教delphi:写你的dll文件(1)【 时间:2007-11-7 | 人气:95 | 收藏本文 】 【 字体:大 中 小 】一、开使你的第一个DLL专案 1.File->Close all->File->NewDLL 代码:/自动产生Code如下 library Project2; /这有段废话 uses SysUtils, Classes; $R *.RES begin end. 2.加个Func进来: 代码:library Project2; uses SysUtils, Classes; Function MyMax ( X , Y : integer ) :

2、integer ; stdcall ; begin if X > Y then Result := X else Result := Y ; end ; /切记:Library 的名字大小写没关系,可是DLL-Func的大小写就有关系了。 / 在 DLL-Func-Name写成MyMax与myMAX是不同的。如果写错了,立即 / 的结果是你叫用到此DLL的AP根本开不起来。 /参数的大小写就没关系了。甚至不必同名。如原型中是 (X,Y:integer)但引 / 用时写成(A,B:integer),那是没关系的。 /切记:要再加个stdcall。书上讲,如果你是用Delphi写DLL,且希

3、望不仅给 / Delphi-AP也希望BCB/VC-AP等使用的话,那你最好加个Stdcall ; 的指示 /参数型态:Delphi有很多种它自己的变量型态,这些当然不是DLL所喜欢的 / ,Windows/DLL的母语应该是C。所以如果要传进传出DLL的参数,我们 / 尽可能照规矩来用。这两者写起来,后者会麻烦不少。如果你对C不熟 / 的话,那也没关系。我们以后再讲。 $R *.RES begin end. 3.将这些可共享的Func送出DLL,让外界就是你的Delphi-AP啦使用:光如此,你的AP还不能用到这些,你还要加个Exports才行。 代码: $R *.RES exports M

4、yMax ; begin end. 4.好了,可以按 Ctrl-F9编译了。此时可不要按F9。DLL不是EXE不可单独执行的,如果你按F9,会有ErrorMsg的。这时如果DLL有Error,请修正之。再按Ctrl-F9。此时可能有Warning,不要紧,研究一下,看看就好。再按Ctrl-F9,此时就Done , Compiled 。同目录就会有个 *.dll 。恭喜,大功告成了。 二、进行测试:开个新application: 1.加个TButton 代码:ShowMessage ( IntToStr(MyMax(30,50) ) ; 2.告知Exe到那里抓个Func 代码:/在Form,in

5、terface,var后加 Function MyMax ( X , Y : integer ) : integer ; stdcall ; external 'MyTestDLL.dll' ; / MyTestDLL.dll为你前时写的DLL项目名字 / DLL名字大小写没关系。不过记得要加 extension的 .DLL。在Win95或NT, / 是不必加 extension,但这两种OS,可能越来越少了吧。要加extension 可以了,简单吧。上面的例子是不是很简单?熟悉Delphi的朋友可以看出以上代码和一般的Delphi程序的编写基本是相同的,只是在TestDll函

6、数后多了一个stdcall参数并且用exports语句声明了TestDll函数。只要编译上面的代码,就可以玫揭桓雒?a href='/html/xueyuan/chengxukaifa/Delphijiaocheng'>Delphi.dll的动态链接库。现在,让我们来看看有哪些需要注意的地方:1.在DLL中编写的函数或过程都必须加上stdcall调用参数。在Delphi 1或Delphi 2环境下该调用参数是far。从Delphi 3以后将这个参数变为了stdcall,目的是为了使用标准的Win32参数传递技术来代替优化的register参数。忘记使用stdcall参数是

7、常见的错误,这个错误不会影响DLL的编译和生成,但当调用这个DLL时会发生很严重的错误,导致操作系统的死锁。原因是register参数是Delphi的默认参数。 2.所写的函数和过程应该用exports语句声明为外部函数。 正如大家看到的,TestDll函数被声明为一个外部函数。这样做可以使该函数在外部就能看到,具体方法是单激鼠标右键用“快速查看(Quick View)”功能查看该DLL文件。(如果没有“快速查看”选项可以从Windows CD上安装。)TestDll函数会出现在Export Table栏中。另一个很充分的理由是,如果不这样声明,我们编写的函数将不能被调用,这是大家都不愿看到的

8、。 3.当使用了长字符串类型的参数、变量时要引用ShareMem。 Delphi中的string类型很强大,我们知道普通的字符串长度最大为256个字符,但Delphi中string类型在默认情况下长度可以达到2G。(对,您没有看错,确实是两兆。)这时,如果您坚持要使用string类型的参数、变量甚至是记录信息时,就要引用ShareMem单元,而且必须是第一个引用的。既在uses语句后是第一个引用的单元。如下例: uses ShareMem, SysUtils, Classes; 还有一点,在您的工程文件(*.dpr)中而不是单元文件(*.pas)中也要做同样的工作,这一点Delphi自带的帮助

9、文件没有说清楚,造成了很多误会。不这样做的话,您很有可能付出死机的代价。避免使用string类型的方法是将string类型的参数、变量等声明为Pchar或ShortString(如:s:string10)类型。同样的问题会出现在当您使用了动态数组时,解决的方法同上所述。 手把手教delphi:写你的dll文件(2)【 时间:2007-11-7 | 人气:88 | 收藏本文 】 【 字体:大 中 小 】在Delphi中静态调用DLL top 调用一个DLL比写一个DLL要容易一些。首先给大家介绍的是静态调用方法,稍后将介绍动态调用方法,并就两种方法做一个比较。同样的,我们先举一个静态调用的例子。

10、 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; procedure Button1Click(Sender: TObject); private Private declarations public Public declarations end; var Form1: TForm1; implemen

11、tation $R *.DFM /本行以下代码为我们真正动手写的代码 function TestDll(i:integer):integer;stdcall; external Delphi.dll; procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Text:=IntToStr(TestDll(1); end; end. 上面的例子中我们在窗体上放置了一个编辑框(Edit)和一个按钮(Button),并且书写了很少的代码来测试我们刚刚编写的Delphi.dll。大家可以看到我们唯一做的工作是将TestDll函数的说明部分放

12、在了implementation中,并且用external语句指定了Delphi.dll的位置。(本例中调用程序和Delphi.dll在同一个目录中。)让人兴奋的是,我们自己编写的TestDll函数很快被Delphi认出来了。您可做这样一个实验:输入“TestDll(”,很快Delphi就会用fly-by提示条提示您应该输入的参数是什么,就像我们使用Delphi中定义的其他函数一样简单。注意事项有以下一些: 一、调用参数用stdcall 和前面提到的一样,当引用DLL中的函数和过程时也要使用stdcall参数,原因和前面提到的一样。 二、用external语句指定被调用的DLL文件的路径和名称

13、 正如大家看到的,我们在external语句中指定了所要调用的DLL文件的名称。没有写路径是因为该DLL文件和调用它的主程序在同一目录下。如果该DLL文件在C:,则我们可将上面的引用语句写为external C:Delphi.dll。注意文件的后缀.dll必须写上。 三、不能从DLL中调用全局变量 如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。 四、被调用的DLL必须存在 这一点很重要,使用静态调用方法时要求所调用的D

14、LL文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.dll文件”等运行错误。 在Delphi中动态调用DLL top 动态调用DLL相对复杂很多,但非常灵活。为了全面的说明该问题,这次我们举一个调用由C+编写的DLL的例子。首先在C+中编译下面的DLL源程序。 #include extern ”C” _declspec(dllexport) int WINAPI TestC(int i) return i; 编译后生成一个DLL文件,在这里我们称该文件为Cpp.dll,该DLL中只有一个返回整数类型的函数T

15、estC。为了方便说明,我们仍然引用上面的调用程序,只是将原来的Button1Click过程中的语句用下面的代码替换掉了。 procedure TForm1.Button1Click(Sender: TObject); type TIntFunc=function(i:integer):integer;stdcall; var Th:Thandle; Tf:TIntFunc; Tp:TFarProc; begin Th:=LoadLibrary(Cpp.dll); 装载DLL if Th>0 then try Tp:=GetProcAddress(Th,PChar(TestC); if

16、Tp<>nil then begin Tf:=TIntFunc(Tp); Edit1.Text:=IntToStr(Tf(1); 调用TestC函数 end else ShowMessage(TestC函数没有找到); finally FreeLibrary(Th); 释放DLL end else ShowMessage(Cpp.dll没有找到); end; 大家已经看到了,这种动态调用技术很复杂,但只要修改参数,如修改LoadLibrary(Cpp.dll)中的DLL名称为Delphi.dll就可动态更改所调用的DLL。 一、定义所要调用的函数或过程的类型 在上面的代码中我们定义

17、了一个TIntFunc类型,这是对应我们将要调用的函数TestC的。在其他调用情况下也要做同样的定义工作。并且也要加上stdcall调用参数。 二、释放所调用的DLL 我们用LoadLibrary动态的调用了一个DLL,但要记住必须在使用完后手动地用FreeLibrary将该DLL释放掉,否则该DLL将一直占用内存直到您退出Windows或关机为止。 现在我们来评价一下两种调用DLL的方法的优缺点。静态方法实现简单,易于掌握并且一般来说稍微快一点,也更加安全可靠一些;但是静态方法不能灵活地在运行时装卸所需的DLL,而是在主程序开始运行时就装载指定的DLL直到程序结束时才释放该DLL,另外只有基

18、于编译器和链接器的系统(如Delphi)才可以使用该方法。动态方法较好地解决了静态方法中存在的不足,可以方便地访问DLL中的函数和过程,甚至一些老版本DLL中新添加的函数或过程;但动态方法难以完全掌握,使用时因为不同的函数或过程要定义很多很复杂的类型和调用方法。对于初学者,笔者建议您使用静态方法,待熟练后再使用动态调用方法。 使用DLL的实用技巧 top 一、编写技巧 1 、为了保证DLL的正确性,可先编写成普通的应用程序的一部分,调试无误后再从主程序中分离出来,编译成DLL。 2 、为了保证DLL的通用性,应该在自己编写的DLL中杜绝出现可视化控件的名称,如:Edit1.Text中的Edit

19、1名称;或者自定义非Windows定义的类型,如某种记录。 3 、为便于调试,每个函数和过程应该尽可能短小精悍,并配合具体详细的注释。 4 、应多利用try-finally来处理可能出现的错误和异常,注意这时要引用SysUtils单元。 5 、尽可能少引用单元以减小DLL的大小,特别是不要引用可视化单元,如Dialogs单元。例如一般情况下,我们可以不引用Classes单元,这样可使编译后的DLL减小大约16Kb。 二、调用技巧 1 、在用静态方法时,可以给被调用的函数或过程更名。在前面提到的C+编写的DLL例子中,如果去掉extern ”C”语句,C+会编译出一些奇怪的函数名,原来的Test

20、C函数会被命名为TestC$s等等可笑的怪名字,这是由于C+采用了C+ name mangling技术。这个函数名在Delphi中是非法的,我们可以这样解决这个问题: 改写引用函数为 function TestC(i:integer):integer;stdcall; external Cpp.dll;name TestC$s; 其中name的作用就是重命名。 2 、可把我们编写的DLL放到Windows目录下或者Windowssystem目录下。这样做可以在external语句中或LoadLibrary语句中不写路径而只写DLL的名称。但这样做有些不妥,这两个目录下有大量重要的系统DLL,如果您编的DLL与它们重名的话其后果简直不堪设想,况且您的编程技术还不至于达到将自己编写的DLL放到系统目录中的地步吧! 三、调试技巧1 、我们知道DLL在编写时是不能运行和单步调试的。有一个办法可以,那就是在Run|paramete

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论