您的位置:首页网络冲浪网络技术 → Delphi中动态链接库(DLL)的建立和使用

Delphi中动态链接库(DLL)的建立和使用

时间:2005/12/12 20:13:00来源:本站整理作者:我要评论(0)

动态链接库是一个能够被应用程序和其它的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下程序组织的一种重要方式,使用动态链接库可以极大地保护用户在不同开发工具、不同时期所做的工作,提高编程效率。

相关视频

    没有数据

相关阅读 iPhone数据迁移怎么用 iOS 12.4数据迁移功能使用教程dnfhello特权专区活动地址 dnfhello特权专区黑钻礼包领取地址dnfhello语音打团开黑领福利活动地址 dnfhello语音黑钻礼包领取地ELDEN RING什么时候出 ELDEN RING发售时间一览剑士kenshi巨人瑞怎么招募 剑士kenshi巨人瑞招募方法剑士kenshi属性作用影响一览 剑士kenshi属性有什么用剑士kenshi怎么操作 剑士kenshi按键操作说明剑士kenshi开锁怎么学 剑士kenshi开锁技能学习方法

文章评论
发表评论

热门文章 小米路由器设置教程附共享有线路由后再接无TP-link无线路由器设置D-Link DI-524M路由器

最新文章 百度网盘解除黑名单摆百度不收录怎么办 百度 10款免费开源图表插件推荐ssid隐藏了怎么办?隐藏SSID的无线网络如何OneDNS设置教程两块网卡访问不同网络案例分享

人气排行 宽带连接图标不见了怎么办 宽带连接图标怎么dell 服务器开机总是提示按F1才能进系统解决dns是什么?dns怎么设置?buffalo无线路由器设置图文教程哪种WIFI无线各种加密方式更安全?ADSL宽带连接错误(720)及解决方法双网卡同时上内外网设置教程公司网络综合布线图解