手把手教delphi:写你的dll文件(2)


======================================================
注:本文源代码点此下载
======================================================

在delphi中静态调用dll top

调用一个dll比写一个dll要容易一些。首先给大家介绍的是静态调用方法,稍后将介绍动态调用方法,并就两种方法做一个比较。同样的,我们先举一个静态调用的例子。

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;

implementation

{$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函数的说明部分放在了implementation中,并且用external语句指定了 delphi.dll的位置。(本例中调用程序和delphi.dll在同一个目录中。)让人兴奋的是,我们自己编写的testdll函数很快被 delphi认出来了。您可做这样一个实验:输入“testdll(”,很快delphi就会用fly-by提示条提示您应该输入的参数是什么,就像我们 使用delphi中定义的其他函数一样简单。注意事项有以下一些:

一、调用参数用stdcall

和前面提到的一样,当引用dll中的函数和过程时也要使用stdcall参数,原因和前面提到的一样。

二、用external语句指定被调用的dll文件的路径和名称

正如大家看到的,我们在external语句中指定了所要调用的dll文件的名称。没有写路径是因为该dll文件和调用它的主程序在同一目录下。如果该 dll文件在c:",则我们可将上面的引用语句写为external ’c:"delphi.dll’。注意文件的后缀.dll必须写上。

三、不能从dll中调用全局变量

如果我们在dll中声明了某种全局变量,如:var s:byte 。这样在dll中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给dll。

四、被调用的dll必须存在

这一点很重要,使用静态调用方法时要求所调用的dll文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.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中只有一个返回整数类型的函数testc。为了方便说明,我们仍然引用上面的调用程序,只是将原来的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 tp一、定义所要调用的函数或过程的类型

在上面的代码中我们定义了一个tintfunc类型,这是对应我们将要调用的函数testc的。在其他调用情况下也要做同样的定义工作。并且也要加上stdcall调用参数。

二、释放所调用的dll

我们用loadlibrary动态的调用了一个dll,但要记住必须在使用完后手动地用freelibrary将该dll释放掉,否则该dll将一直占用内存直到您退出windows或关机为止。

现在我们来评价一下两种调用dll的方法的优缺点。静态方法实现简单,易于掌握并且一般来说稍微快一点,也更加安全可靠一些;但是静态方法不能灵活地在 运行时装卸所需的dll,而是在主程序开始运行时就装载指定的dll直到程序结束时才释放该dll,另外只有基于编译器和链接器的系统(如delphi) 才可以使用该方法。动态方法较好地解决了静态方法中存在的不足,可以方便地访问dll中的函数和过程,甚至一些老版本dll中新添加的函数或过程;但动态 方法难以完全掌握,使用时因为不同的函数或过程要定义很多很复杂的类型和调用方法。对于初学者,笔者建议您使用静态方法,待熟练后再使用动态调用方法。

使用dll的实用技巧 top

一、编写技巧

1 、为了保证dll的正确性,可先编写成普通的应用程序的一部分,调试无误后再从主程序中分离出来,编译成dll。

2 、为了保证dll的通用性,应该在自己编写的dll中杜绝出现可视化控件的名称,如:edit1.text中的edit1名称;或者自定义非windows定义的类型,如某种记录。

3 、为便于调试,每个函数和过程应该尽可能短小精悍,并配合具体详细的注释。

4 、应多利用try-finally来处理可能出现的错误和异常,注意这时要引用sysutils单元。

5 、尽可能少引用单元以减小dll的大小,特别是不要引用可视化单元,如dialogs单元。例如一般情况下,我们可以不引用classes单元,这样可使编译后的dll减小大约16kb。

二、调用技巧

1 、在用静态方法时,可以给被调用的函数或过程更名。在前面提到的c++编写的dll例子中,如果去掉extern ”c”语句,c++会编译出一些奇怪的函数名,原来的testc函数会被命名为@testc$s等等可笑的怪名字,这是由于c++采用了c++ name mangling技术。这个函数名在delphi中是非法的,我们可以这样解决这个问题:

改写引用函数为

function testc(i:integer):integer;stdcall;

external ’cpp.dll’;name ’@testc$s’;

其中name的作用就是重命名。

2 、可把我们编写的dll放到windows目录下或者windows"system目录下。这样做可以在external语句中或loadlibrary 语句中不写路径而只写dll的名称。但这样做有些不妥,这两个目录下有大量重要的系统dll,如果您编的dll与它们重名的话其后果简直不堪设想,况且您 的编程技术还不至于达到将自己编写的dll放到系统目录中的地步吧!

三、调试技巧

1 、我们知道dll在编写时是不能运行和单步调试的。有一个办法可以,那就是在run|parameters菜单中设置一个宿主程序。在local页的host application栏中添上宿主程序的名字就可进行单步调试、断点观察和运行了。

2 、添加dll的版本信息。开场白中提到了版本信息对于dll是很重要的,如果包含了版本信息,dll的大小会增加2kb。增加这么一点空间是值得的。很不 幸我们如果直接使用project|options菜单中version选项是不行的,这一点delphi的帮助文件中没有提到,经笔者研究发现,只要加 一行代码就可以了。如下例:

library delphi;

uses

sysutils,

classes;

{$r *.res}

//注意,上面这行代码必须加在这个位置

function testdll(i:integer):integer;stdcall;

begin

result:=i;

end;

exports

testdll;

begin

end.

3 、为了避免与别的dll重名,在给自己编写的dll起名字的时候最好采用字符数字和下划线混合的方式。如:jl_try16.dll。

4 、如果您原来在delphi 1或delphi 2中已经编译了某些dll的话,您原来编译的dll是16位的。只要将源代码在新的delphi 3或delphi 4环境下重新编译,就可以得到32位的dll了。

[后记]:除了上面介绍的dll最常用的使用方法外,dll还可以用于做资源的载体。例如,在windows中更改图标就是使用的dll中的资源。另外,熟练掌握了dll的设计技术,对使用更为高级的ole、com以及activex编程都有很多益处。


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值