首页 > 编程知识 正文

使用动态链接库时显示链接和隐式链接的区别,动态链接库调用

时间:2023-05-04 19:35:16 阅读:206559 作者:4173

1 究竟什么是DLL 
    动态链接库是程序模块,它包括代码、数据或资源,能够被其他的Wi n d o w s应用程序共享。DLL的主要特点之一是应用程序可以在运行时调入代码执行,而不是在编译时链接代码,因此,多个应用程序可以共享同一个D L L的代码。事实上,文件Kernel32.dll、User32.dll、GDI32.dll就是核心Win32系统的动态链接库。Kernel.dll负责内存、进程和线程的管理。USER32.DLL包含了一些程序,是创建窗口和处理Win32消息的用户接口。GDI32.DLL负责处理图形。你还会听说其他的系统DLL,譬如AdvAPI32.dll和ComDlg32.dll,它们分别处理对象安全性/注册操作和通用对话框。
    使用动态链接库的另一个特点是有利于应用程序的模块化。这样就简化了应用程序的修改,因为一般只需要修改DLL,而不是整个应用程序。Windows环境自身就是模块化类型的典型实例。每当安装一个新设备,就安装一个设备驱动程序(即DLL ),使设备能够与Windows相互通信。在磁盘上,一个DLL基本上类似于一个Windows可执行文件(*.EXE)。一个主要的区别是,DLL不是一个独立的可执行文件,尽管它可能包含了可执行代码。大部分DLL文件的扩展名是.dll,也有的可能是.drv(设备驱动程序)、.sys(系统文件)、.fon(字体文件),这些不包含可执行代码。
    注意Delphi引入了一种叫做程序包的特殊用途的DLL,它应用于Delphi和C++编程环境。
    DLL通过动态链接技术(dynamic linking)与其他应用程序共享代码,这将在本章后面部分讨论。总之,当一个应用程序使用了一个DLL,Win32系统会确保内存中只有一个该DLL的拷贝,这是通过内存映射文件来实现的。DLL首先被调入Win32的全局堆,然后映射到调用这个DLL进程的地址空间。
    在Win32系统中,每个进程都被分配有自己的3 2位线性地址空间。当一个DLL被多个进程调用时,每个进程都会获得该DLL的一份映像。因此,在16位Windows中,程序代码、数据、资源不被进程共享,而在Win32中,DLL是可以被看作是属于调用该DLL进程自己的代码。
    但这并不意味着,如果多进程调用一个DLL,物理内存就分配有该DLL的每个实例。通过从系统的全局堆到调用该DLL的每一进程的地址空间的映射,DLL映像置于每个进程的地址空间。至少在理想情况下应这样。
    设置DLL的首选基地址
    如果DLL被调入进程的地址空间时设置了基地址,这样DLL数据就可以被共享。如果DLL的基地址与已经分配的DLL地址重叠的话,Win32重新分配基地址。这样,每一个重新分配的DLL实例都有自己的物理上的内存空间和交换文件空间。
    这是很关键的,通过使用$IMAGEBASE指示符,给每个DLL都设置一个基地址,这样不会引起冲突或不会出现地址重叠。如果有多个应用程序都调用同一个D L L,设置一个唯一的基地址,这样无论是在进程的低端地址或者是在一般的D L L (如V C L包)的高端地址,都不会引起冲突。一般可执行文件(EXE和DLL)缺省的基地址为$400000,这就意味着,除非修改DLL的基地址,否则就会与主程序的基地址引起冲突,因此进程间也就不能共享DLL的数据。
    在调用时,DLL不需要重新分配或安装,因为它保存在本地磁盘上,DLL的内存页面被直接映射到磁盘上的DLL文件。DLL代码不需占用系统页面文件(也叫交换文件)的空间。这就是为什么系统提交页的总数和大小可能比系统交换文件加内存要大。
    你可以参阅Delphi的在线帮助中的“Image Base Address”,那里有使用$IMAGEBASE指示符的详细介绍。
    有关D L L的一些术语如下: 
    . 应用程序,一个扩展名为.exe的Windows程序。
    . 可执行文件,一个包含可执行代码的文件,它包括.dll文件和.exe文件。
    . 实例,当提到应用程序和DLL时,在内存中出现的可执行文件就是实例。Win32系统通过实例句柄的方式来引用实例。例如,如果一个应用程序运行两次,就会有应用程序的两个实例,同时就有两个实例句柄。当一个DLL被调入时,实例及其相应的实例句柄同时产生。应该注意的是,这里所提的实例与类的实例不能混淆。
    . 模块,在32位Windows系统中,模块和实例可以说是同义的。而在16位的Windows系统中,是建立一个模块数据库来管理模块的,一个模块对应一个模块句柄。在Win32中,应用程序的每一个实例都拥有自己的地址空间;所以,没有必要为模块单独指定标识符。不过,微软仍然保留了它自己的术语。注意一点,模块和实例是同一个概念。
     . 任务,Windows是一个多任务(或任务切换)环境,所以它必须能够为运行的多个实例合理分配系统资源和时间。于是,Windows建立一个任务数据库,这个数据库包括任务的实例句柄和其他必要信息,以此实现任务切换功能。任务是Windows用来管理和分配资源与时间段的重要元素。

9.2 静态链接与动态链接
    静态链接是指Delphi编译器把要调用的函数和过程编译成可执行代码。函数的代码可存留在应用程序的.dpr文件或一单元中。当链接用户的应用程序时,这些函数与过程便成为最终的可执行文件的一部分.

.......
       
    假设有两个应用程序,都要调用一个单元的同一个函数,当然,这两个应用程序都要在其uses子句中包含该单元。如果这两个程序要同时运行,那么内存中就存在两份该函数,如果还有第三个这样的应用程序,内存中就会有第三份该函数的实例,这样,就会三次占据内存。这个小例子就表明了动态链接的优越性之一。函数通过动态链接,被放到一个DLL中。那么如果一个应用程序把该函数调入内存,其他应用程序就可以通过映射D L L的映像到自己进程内存空间来共享代码。理论上讲,最终结果是内存中只存在该DLL的一份实例。
    对于动态链接,在程序运行时,通过引用一个外部函数(该函数包含在DLL中)而将该函数链接到可执行文件中。其中的引用可以在应用程序中声明,但是通常情况下是放在一个专门的引入(import)单后面的字符串就是该DLL的名称。要使用这个单元,应用程序只需把MaxUnit加到它的uses子句中即可。
    当这个程序运行时,该DLL就会自动地被调入内存,并且任何需要调用Max()的程序都被链接到这个DLL中的Max()函数。
    调用DLL有两种方式,这是其中一种,叫隐式调用,就是让Windows在应用程序调入时自动地调

3 为什么要使用DLL 
    使用D L L有若干理由,其中有一些前面已经提到过了。大体说来,使用动态链接库可以共享代码、系统资源,可以隐藏实现的代码或底层的系统例程、设计自定义控件。下面将分别讨论这几个方面的内容。
  3.1 共享代码、资源和数据
    在本章节前面已经提到,共享代码是创建动态链接库的主要目的所在。但与单元的代码共享不同,DLL的代码可以被任何Windows应用程序共享,而单元代码的共享局限于Delphi应用程序。
    另外,DLL提供了共享资源的途径,诸如位图、字体、图标等等这些都可以放到一个资源文件中,并直接链接到应用程序。如果把这些资源放到DLL中,那么就可以让许多应用程序使用,而不必在内存里重复装入这些资源。
    这行代码的意思表明,ClientToSreen()在动态链接库User32.dll中,它的名称叫ClientToSreen. 
    在1 6位的Windows中,DLL有自己的数据段,于是,所有要调用同一个DLL的应用程序能够访问同一个全局变量和静态变量。但在Win32系统中,这就不同了。因为DLL的映像被映射到每个进程的地址空间,该DLL的所有数据属于映射到的进程。值得一说的是,尽管进程间不能共享DLL的数据,但是同一个进程的所有线程可以共享,因为线程是相互独立的,所以在访问某一DLL的全局变量时,务必小心,防止引起冲突。
    但这并不意味着没有办法实现在进程间共享一个DLL的数据。一个技术可以通过内存映射文件的方法在内存中创建一个共享的区域。一切需调用D L L的应用程序都可以读这些存储在内存中的共享区域的数据。
  3.2 隐藏实现的细节
    有些时候,你可能想隐藏例程实现的细节,DLL就可以实现这一点。不管为何要隐藏你的代码,DLL可以使函数被应用程序访问,而其中的代码细节不被显现,你所要做的只是提供别人能访问DLL的接口。你也许认为Delphi的编译单元(DCU)也可以隐藏细节,但是DCU只适用于Delphi应用程序,而且还受版本的局限。而DLL与语言无关,所以,创建的DLL可以被C++、VB或其他任何支持DLL的语言调用。
    Windows单元是Win32 DLL的接口单元。Delphi提供了Win32 API的源文件,其一是Windows单元的源文件windows.pas. 
  3.3 自定义控件
    自定义控件通常放在DLL中。这些控件不同于Delphi的自定义组件。自定义控件是在Windows下注册,并且可以在任何Windows开发环境中使用。将这些类型的自定义控件加进DLL中,是考虑到即使有多个应用程序要使用这些自定义控件,内存中也只有该控件的一份实例。
    注意其实将自定义控件加进DLL这种机制已经过时,现在,微软使用OLE和ActiveX控件,自定义控件已很少见了。 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。