Delphi 中动态链接库(DLL)的建立和使用_信息技术论文
关键词: |
动态链接库是一个能够被应用程序和其它的dll调用的过程和函数的集合体,它里面包含的是公共代码或资源。由于dll代码使用了内存共享技术,在某些地方windows也给了dll一些更高的权限,因而dll中可以实现一些一般程序所不能实现的功能,如实现windows的hook、isapi等。同时,dll还为不同语言间代码共享提供了一条方便的途径。因而dll在编程时应用较为广泛,本文将介绍如何在 delphi 中建立和使用dll。 一.dll 库内存共享机制 从使用效果看,dll和unit 很像,它们都可以被别的工程模块所调用,但二者在内部的实现机制上确存在着差别。如果一个程序模块中用uses语句引用了某个unit,编译程序在编译该模块时,便会连同unit一起编译,并把编译后的可执行代码链接到本程序模块中,这就是一个程序模块能够调用所引用unit中过程和函数的原因。当同一个unit被多个工程所引用时,则每个工程中都含有该unit的可执行代码,当含有该unit的多个工程同时执行时,unit的可执行代码会随不同工程而多次被调入内存,造成内存资源的浪费。dll则不同,它即使被某个工程调用,编译后仍是独立的,也就是说编译后,一个dll库形成一个单独的可执行文件,而不与任何其它的可执行文件连接在一起,因而dll库并不从属于某个特定的工程,当多个工程调用同一个dll库时只有第一个工程把dll库调入内存,其余工程并不重复调入同一个dll库到内存,而是到同一个共享内存区读取。并且,dll的执行代码是在程序运行期间动态调入的,而不是如unit在程序运行时就与整个工程一起调入内存。这样便可消除unit带来的相同代码多处占用内存的弊病。 二 delphi中dll库的建立 在delphi环境中,编写一个dll同编写一个一般的应用程序并没有太大的区别。事实上作为dll主体的dll函数的编写,除了在内存、资源的管理上有所不同外,并不需要其它特别的手段。 一般工程文件的格式为: program 工程标题;
uses 子句;
程序体 而dlls工程文件的格式为: library 工程标题;
uses 子句;
exprots 子句;
程序体 它们主要的区别有两点: 1.一般工程文件的头标用program关键字,而dll工程文件头标用library 关键字。不同的关键字通知编译器生成不同的可执行文件。用program关键字生成的是.exe文件,而用library关键字生成的是.dll文件; 2.假如dll要输出供其它应用程序使用的函数或过程,则必须将这些函数或过程列在exports子句中。而这些函数或过程本身必须用export编译指令进行编译。 在delphi主菜单file 中选new...项,在弹出的窗口中双击dll图标,便会自动给出dll源模块框架,如下: library project1; {...注释...} uses sysutils, classes; begin end.
接下来便可在uses和begin之间加入想在该dll中实现的过程和函数的定义,并用export和exprots保字把它们引出,以便别的模块引用,在begin和end之间加入初始化代码,初始化代码是用来对dll变量初始化的。应注意,即便无初始化代码begin与end也不可省略,如下例: library minmax; function min(x, y: integer): integer; export; begin if x < y then min := x else min := y; end; function max(x, y: integer): integer; export; begin if x > y then max := x else max := y; end; exports min index 1, max index 2; begin end.
经编译后,并以minmax.dll存盘后,一个dll库文件便形成了。 三 dll库的访问 访问dll库有两种方式,一种是静态引用,另一种是动态引用。 用静态引用这种方法装入dll要做两件事情:为dll 库创建一个输入单元,以及用uses把输入单元连接到要使用dll 函数的程序模块中。为dll库创建的输入单元与普通的单元的区别仅在于:在它的接口处声明的过程、函数,并不在它的实现部分给出真正的实现代码,而是用external关键字把过程、函数的实现细节委托给外部dll模块。 external命令的使用语法如下: procedure /function 过程/函数名;external dll模块名; 下面给出为上面创建的minmax.dll库写的输入单元源文件testdll .pas,从中可看出输入单元 与一般 单元的一些差别,代码如下所示: unit testdll; interface uses function min (x, y: integer): integer; function max (x, y: integer): integer;
implementation
function min; external ‘minmax.dll’; function max; external ‘minmax.dll’; end.
一个应用程序若想调用minmax.dll中的函数,只须在其uses语句中加入testdll 单元即可。 动态装入dll,要用到windows的三个api函数。loadlibrary、freelibrary和getprocaddress 。loadlibrary函数用来装入dll库,其调用格式如下: function loadlobrary (dllfilename:pchar): thandle: 当不再需要一个dll库时,应调用freelibrary函数将其释放,以空出宝贵的内存资源,其调用格式如下: procedure freelibrary (libmodule:thandle) libmodule 为由loadlibrary调用得到的dll库句柄。在用loadlobrary 函数装入某个dll库和调用freelibrary释放该dll库之间的程序段中, 可以使用该dll库中的过程和函数,具体使用方法是:用getprocaddress函数把dll库中函数的地址传递给程序中某个函数变量,再用该变量实现dll函数的调用。getprocaddress函数声名如下, function getprocaddress (libmodule:thandle:procname:pchar):tfarproc:
如下例所示: type ttimerec = record second: integer; minute: integer; hour: integer; end; tgettime = procedure(var time: ttimerec); thandle = integer; var time: ttimerec; handle: thandle; gettime: tgettime; ... begin handle := loadlibrary('datetime.dll'); if handle <> 0 then begin @gettime := getprocaddress(handle, 'gettime'); if @gettime <> nil then begin gettime(time); with time do writeln('the time is ', hour, ':', minute, ':', second); end; freelibrary(handle); end; end; 在调用动态链接库时应注意, 所需动态链接库须与应用程序在同一目录或windows system 目录下。 动态链接库是 windows下程序组织的一种重要方式,使用动态链接库可以极大地保护用户在不同开发工具、不同时期所做的工作,提高编程效率。 邮编:831100 电话:0994-2348728 email:jxzt-cj@mail.xj.cninfo.net |