动态连接库设计_第1页
动态连接库设计_第2页
动态连接库设计_第3页
动态连接库设计_第4页
动态连接库设计_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

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

文档简介

1、网络编程与开发技术网络编程与开发技术 天津职业技术师范大学天津职业技术师范大学信息学院信息学院第六章第六章 动态连接库设计动态连接库设计内内 容容 提提 要要1 1、动态连接库的特点、动态连接库的特点2 2、创建动态连接库、创建动态连接库3 3、调用动态连接库、调用动态连接库4 4、动态连接库在网络程序中的应用、动态连接库在网络程序中的应用6.1 6.1 动态连接库的特点动态连接库的特点 第六章第六章 动态连接库的特点动态连接库的特点 动态连接库(动态连接库(Dynamic-Link Library)是一些编译过的可执行代码)是一些编译过的可执行代码模块,可以在应用程序中或其它模块,可以在应用

2、程序中或其它DLL中被调用,是中被调用,是Windows的重要组成的重要组成要素。动态连接库是一个包括了若干函数的可执行模块,其包含的函数要素。动态连接库是一个包括了若干函数的可执行模块,其包含的函数可以由可以由Windows应用程序调用以执行一些功能。应用程序调用以执行一些功能。Windows内核的三个模内核的三个模块块USER.EXE、KENERL.EXE和和GDI.EXE实际上都是动态连接库,分实际上都是动态连接库,分别提供用户消息服务、进程管理、图形输出等服务。在别提供用户消息服务、进程管理、图形输出等服务。在WindowsSystem目录下,凡是以目录下,凡是以.DLL、.DRV、.

3、FON、.SYS和许多以和许多以.EXE为扩展名的为扩展名的系统文件都是动态连接库。系统文件都是动态连接库。 多个应用程序可以同时调用同一个动态连接库时,内存中只有该动多个应用程序可以同时调用同一个动态连接库时,内存中只有该动态连接库的一个实例,这使系统能高效经济地使用内存。动态连接库中态连接库的一个实例,这使系统能高效经济地使用内存。动态连接库中的执行模块与调用它的应用程序是完全分开的。几个函数可以放于一个的执行模块与调用它的应用程序是完全分开的。几个函数可以放于一个动态连接库中,应用程序使用这些函数,就象它们是应用程序可执行代动态连接库中,应用程序使用这些函数,就象它们是应用程序可执行代码

4、的一部分。码的一部分。 6.1 6.1 动态连接库的特点动态连接库的特点 第六章第六章 动态连接库的特点动态连接库的特点 升级到升级到 DLL 更为容易。更为容易。DLL中的函数更改时,只要函数的参数和返中的函数更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。反,静态链接的对象代码要求在函数更改时重新链接应用程序。 动态连接库可以有自己的数据段,但没有自己的堆栈,动态连接动态连接库可以有自己的数据段,但没有自己的堆栈,动态连接库与调用它的应用

5、程序使用相同的堆栈模式,这减少了编程设计上的库与调用它的应用程序使用相同的堆栈模式,这减少了编程设计上的不便。同时动态连接库实现了代码的封装性,使得程序简洁明晰。不便。同时动态连接库实现了代码的封装性,使得程序简洁明晰。 支持动态连接库的创建与具体的编程语言及编译器无关,只要遵支持动态连接库的创建与具体的编程语言及编译器无关,只要遵守动态连接库的开发规范和编程策略,并安排正确的调用接口,不论守动态连接库的开发规范和编程策略,并安排正确的调用接口,不论用何种编程语言编制的动态连接库都具有通用性。例如在用何种编程语言编制的动态连接库都具有通用性。例如在VC中编制的中编制的动态连接库程序,可用于动态

6、连接库程序,可用于BC、VB、Delphi等多种语言环境中。等多种语言环境中。 6.1 6.1 动态连接库的特点动态连接库的特点 第六章第六章 动态连接库的特点动态连接库的特点 动态连接库函数可以被任何编程语言编写的应用程序所调用,只要动态连接库函数可以被任何编程语言编写的应用程序所调用,只要应用程序使用统一的函数调用规则,即程序与应用程序使用统一的函数调用规则,即程序与 DLL 函数在下列方面必函数在下列方面必须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应用程序负责清理堆栈,以及寄存器中是否传递了任何参数。用程序负责清

7、理堆栈,以及寄存器中是否传递了任何参数。 动态连接库中虽然包含了函数的目标代码,但动态连接库中的函数动态连接库中虽然包含了函数的目标代码,但动态连接库中的函数代码是不被包含在应用程序中的,应用程序只是简单地记录了函数的代码是不被包含在应用程序中的,应用程序只是简单地记录了函数的位置信息(即包含于哪个动态连接库中以及在动态连接库中的位置)。位置信息(即包含于哪个动态连接库中以及在动态连接库中的位置)。有了这些信息后,程序在执行时,即可找到该函数的目标代码。如果有了这些信息后,程序在执行时,即可找到该函数的目标代码。如果应用程序在运行时系统不能找到所需动态连接库,则动态连接库提供应用程序在运行时系

8、统不能找到所需动态连接库,则动态连接库提供的功能对应用程序来说将是不可用的,甚至会因此终止程序的运行。的功能对应用程序来说将是不可用的,甚至会因此终止程序的运行。 6.2 6.2 创建动态连接库创建动态连接库 第五章第五章 多线程结构的网络编程多线程结构的网络编程源代码文件(源代码文件(.c.c)的结构)的结构模块定义文件(模块定义文件(.DEF.DEF)的结构和各段的意义)的结构和各段的意义函数声明文件函数声明文件工程文件工程文件6.2.1 6.2.1 源代码文件(源代码文件(.c.c)的结构)的结构 第六章第六章 动态连接库的特点动态连接库的特点 通常,动态连接库由一个或更多的源代码文件(

9、通常,动态连接库由一个或更多的源代码文件(.c.c)、一)、一个模块定义文件(个模块定义文件(.def.def文件)、一个函数声明文件(文件)、一个函数声明文件(.H.H)、以及)、以及一个工程文件(一个工程文件(.PRJ.PRJ)组成)组成 。 源代码文件中主要包含动态连接库内部函数的定义,内部源代码文件中主要包含动态连接库内部函数的定义,内部函数一般包括三种:入口函数、输出函数和终止函数。函数一般包括三种:入口函数、输出函数和终止函数。6.2.1 6.2.1 源代码文件(源代码文件(.c.c)的结构)的结构 第六章第六章 动态连接库的特点动态连接库的特点源代码文件具体结构示例如下:源代码文

10、件具体结构示例如下:#include #include /入口函数入口函数int FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSeg, WORD int FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) cbHeapSize, LPSTR lpszCmdLine ) if (cbHeapSize!=0) if (cbHeapSize!=0) UnlockData(0); UnlockData(0); /解锁数据

11、段解锁数据段/此处可进行一些用户必要的初始化工作此处可进行一些用户必要的初始化工作return return (1 1); ; /输出函数输出函数int FAR PASCAL ExportFunction1 (int param1,.,char param n) int FAR PASCAL ExportFunction1 (int param1,.,char param n) /. C/. C语言应用程序语言应用程序 /终止函数终止函数/ /int FAR PASCAL WEP ( int /int FAR PASCAL WEP ( int /* *SystemExitSystemExit*

12、 */ ) / ) return(1); return(1); 6.2.1 6.2.1 源代码文件(源代码文件(.c.c)的结构)的结构 第六章第六章 动态连接库的特点动态连接库的特点以上各组成部分及参数的含义:以上各组成部分及参数的含义:1)Windows.h1)Windows.h头文件,它包含有数据类型的定义、头文件,它包含有数据类型的定义、APIAPI入口点定义和其它有用的入口点定义和其它有用的参数信息。参数信息。2)PASCAL2)PASCAL说明符定义该程序的传递参数和净化堆栈的协定(注意:说明符定义该程序的传递参数和净化堆栈的协定(注意:DLLDLL外部传外部传送的指针必须是远指针

13、送的指针必须是远指针FARFAR)。)。3)LibMain3)LibMain函数就象函数就象C C程序中的程序中的Main()Main()一样,是一样,是DLLDLL的入口函数,的入口函数,WindowsWindows每次每次加载加载DLLDLL时都要执行时都要执行LibMain( )LibMain( )函数,它主要用来进行一些初始化工作。函数,它主要用来进行一些初始化工作。LibMainLibMain带四个参数:带四个参数:hInstancehInstance、 wDataSegwDataSeg、cbHeapSizecbHeapSize和和lpszCmdLinelpszCmdLine。hIn

14、stancehInstance是是DLLDLL事例句柄。事例句柄。wDataSegwDataSeg参数是数据段(参数是数据段(DSDS)寄存器值。寄存器值。cbHeapSizecbHeapSize参数是在模块定义文件中定义的堆的大小,参数是在模块定义文件中定义的堆的大小,LibMainLibMain 使用该使用该值使本地堆初始化。值使本地堆初始化。lpszCmdLinelpszCmdLine参数包括命令行信息,但很少被参数包括命令行信息,但很少被DLLDLL使用。使用。 一般来说,这四个参数是制作一般来说,这四个参数是制作DLLDLL通用的参数。通用的参数。 如果不想让如果不想让DLLDLL数

15、据被封住,数据被封住,那么必须调用那么必须调用unlockdataunlockdata恢复正常的非锁状态,如果恢复正常的非锁状态,如果DLLDLL初始化已经成功,初始化已经成功,DLLDLL则则返回返回1 1,若不成功则返回,若不成功则返回0 0值,且值,且 DLLDLL退出系统。退出系统。6.2.1 6.2.1 源代码文件(源代码文件(.c.c)的结构)的结构 第六章第六章 动态连接库的特点动态连接库的特点4) ExportFunction1 4) ExportFunction1 是是DLLDLL的一个输出函数,实现用户所要完的一个输出函数,实现用户所要完成的任务,这部分是成的任务,这部分是

16、DLLDLL的核心。它与一般的核心。它与一般C C语言程序相似,但是语言程序相似,但是所有的外部指针都是远指针所有的外部指针都是远指针FARFAR。一个。一个DLLDLL中可以有多个输出函数。中可以有多个输出函数。5) WEP5) WEP函数是函数是DLLDLL的终止函数,终止函数有时称为退出函数,它的终止函数,终止函数有时称为退出函数,它的名字必须是的名字必须是WEPWEP,且它可以被包括在,且它可以被包括在DLLDLL模块定义文件的模块定义文件的EXPORTSEXPORTS段中。段中。WindowsWindows从内存中卸载从内存中卸载DLLDLL时,调用相应的出口函数时,调用相应的出口函

17、数WEP( )WEP( ),主要做一些清理工作,如释放占用的内存资源;丢弃某些字串、主要做一些清理工作,如释放占用的内存资源;丢弃某些字串、位图等资源;关闭打开的文件等等。位图等资源;关闭打开的文件等等。6.2.2 6.2.2 模块定义文件(模块定义文件(.DEF.DEF)的结构和各段的意义)的结构和各段的意义 第六章第六章 动态连接库的特点动态连接库的特点LIBRARY example LIBRARY example DESCRIPTION example.DLL DESCRIPTION example.DLL EXETYPE WINDOWS EXETYPE WINDOWS CODE PRE

18、LOAD MOVEABLE DISCARDABLE CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE SINGLE DATA PRELOAD MOVEABLE SINGLE HEAPSIZE 1024 HEAPSIZE 1024 EXPORTS EXPORTS ExportFunction1 1 ExportFunction1 1 WEP 2 WEP 2 以上各组成部分及参数的含义:以上各组成部分及参数的含义:1) 1) 关键字关键字LIBRARYLIBRARY是把这个模块视为一个是把这个模块视为一个DLLDLL,库的名字,库的名字

19、exampleexample跟在跟在其后,且必须与该库的名字、其后,且必须与该库的名字、DEFDEF中的中的DLLDLL的文件名相一致。的文件名相一致。2) DESCRIPTION2) DESCRIPTION语句采用一个字符串,其长度可达语句采用一个字符串,其长度可达128128个字符,通常个字符,通常用它来保存模块描述的信息。用它来保存模块描述的信息。 6.2.2 6.2.2 模块定义文件(模块定义文件(.DEF.DEF)的结构和各段的意义)的结构和各段的意义 第六章第六章 动态连接库的特点动态连接库的特点3) EXETYPE windows3) EXETYPE windows语句表明动态库

20、类型。语句表明动态库类型。4) CODE4) CODE语句定义该库代码段的内存属性,语句定义该库代码段的内存属性,MOVEABLEMOVEABLE允许内存管理程序在必允许内存管理程序在必要时移动代码段,要时移动代码段,DISCARDABLEDISCARDABLE表明系统在必要时可以释放代码段空间。表明系统在必要时可以释放代码段空间。5) DATA5) DATA语句定义该库数据段的内存属性,关键字语句定义该库数据段的内存属性,关键字MOVEABLEMOVEABLE允许内存管理程允许内存管理程序在必要时移动内存段,关键字序在必要时移动内存段,关键字SINGLESINGLE是是DLLDLL必要,因为

21、必要,因为DLLDLL总是有一个单一数总是有一个单一数据段,而不管访问它的应用程序的数量。据段,而不管访问它的应用程序的数量。6) HEAPSIZE6) HEAPSIZE语句用来定义一个语句用来定义一个DLLDLL局部堆的初始规模,执行局部内存分配的局部堆的初始规模,执行局部内存分配的DLLDLL必须在库启动时使该堆初始化,堆的大小被传送给必须在库启动时使该堆初始化,堆的大小被传送给DLLDLL的的LiEntryLiEntry的程序。的程序。然后用该堆的大小调用然后用该堆的大小调用LocallnitLocallnit使使DLLDLL的局部堆初始化。的局部堆初始化。 7) EXEPORTS7)

22、EXEPORTS语句列出动态连接库中可以被其它模块调用的输出函数的名字语句列出动态连接库中可以被其它模块调用的输出函数的名字和序号,系统利用这个信息建立一个序数入口值,序数入口值是一个优化的值,和序号,系统利用这个信息建立一个序数入口值,序数入口值是一个优化的值,允许动态连接机制更快块操作且使用较少的内存。允许动态连接机制更快块操作且使用较少的内存。 一般来说,模块定义文件(一般来说,模块定义文件(.DEF.DEF)的结构除取动态库的名字不同外,其它结)的结构除取动态库的名字不同外,其它结构都是固定的。动态连接库模块定义文件用语产生输入文件(构都是固定的。动态连接库模块定义文件用语产生输入文件

23、(.lib.lib)和输出库)和输出库文件(文件(.exp.exp)。连接器使用输出文件建立)。连接器使用输出文件建立.dll.dll文件。文件。 6.2.3 6.2.3 函数声明文件(函数声明文件(.H.H)第六章第六章 动态连接库的特点动态连接库的特点原形函数的功能是进一步声明调用函数的函数名和传递的参数,原形函数的功能是进一步声明调用函数的函数名和传递的参数,其形式为:其形式为: int FAR PASCAL ExportFunction1(int param1,.,char param n) ;int FAR PASCAL ExportFunction1(int param1,.,ch

24、ar param n) ; 6.2.4 6.2.4 工程文件(工程文件(.PRJ.PRJ)第六章第六章 动态连接库的特点动态连接库的特点工程文件包含有工程文件包含有example.Cexample.C、example.DEFexample.DEF两个文件,编译连接两个文件,编译连接工程文件最终生成动态链接库文件。工程文件最终生成动态链接库文件。 6.3 6.3 调用动态连接库调用动态连接库 第五章第五章 多线程结构的网络编程多线程结构的网络编程隐式链接方式加载隐式链接方式加载DLLDLL显示方式加载显示方式加载DLLDLL6.3 6.3 调用动态库调用动态库第六章第六章 动态连接库的特点动态连

25、接库的特点调用调用DLLDLL中函数的方法有两种:中函数的方法有两种:隐式链接:隐式链接:即系统在加载应用程序的同时加载该程序所需的即系统在加载应用程序的同时加载该程序所需的DLLDLL。当程序运行结束时,系统负责卸载当程序运行结束时,系统负责卸载DLLDLL(如还有其它程序使用该(如还有其它程序使用该DLLDLL,则系统对,则系统对DLLDLL的应用记录减的应用记录减1 1,直到所有相关程序都结束对该,直到所有相关程序都结束对该DLLDLL的使用时才完全释放它)。在这种方式下,应用程序需要将的使用时才完全释放它)。在这种方式下,应用程序需要将DLLDLL输入库(输入库(.Lib.Lib)与应

26、用程序相连接,或者在应用程序模块定义)与应用程序相连接,或者在应用程序模块定义文件中,用文件中,用IMPORTSIMPORTS语句列出所要调用语句列出所要调用DLLDLL的函数名。的函数名。显式链接:显式链接:通过使用通过使用Win32 APIWin32 API函数来加载和卸载函数来加载和卸载DLLDLL以达到调以达到调用用DLLDLL的目的。的目的。 两种方法均保留了两种方法均保留了DLLDLL的优点:可修改的优点:可修改DLLDLL而不需要重新编译而不需要重新编译连接应用程序;同时被多个应用程序调用;节省内存和磁盘空间连接应用程序;同时被多个应用程序调用;节省内存和磁盘空间的使用。的使用。

27、 6.3.1 6.3.1 隐式链接方式加载隐式链接方式加载DLLDLL 第六章第六章 动态连接库的特点动态连接库的特点 隐式链接是隐式链接是Win32 APIWin32 API普遍使用的方法。编译器在编译应用程序源普遍使用的方法。编译器在编译应用程序源代码时,如果源代码调用任何外部函数(包括代码时,如果源代码调用任何外部函数(包括DLLDLL函数和代码在另一个函数和代码在另一个目标模块中的函数),则产生的目标码中仅包含对外部函数的引用。随目标模块中的函数),则产生的目标码中仅包含对外部函数的引用。随后,在对目标码进行连接时,如果连接器发现引用的外部函数存在于某后,在对目标码进行连接时,如果连接

28、器发现引用的外部函数存在于某个输入库(个输入库(.Lib.Lib)或在应用程序模块定义文件的)或在应用程序模块定义文件的IMPORTSIMPORTS语句中,它便语句中,它便认为该外部函数是认为该外部函数是DLLDLL中的函数,因此只是简单地在可执行文件中加入中的函数,因此只是简单地在可执行文件中加入DLLDLL的存放地址信息。的存放地址信息。 当运行不包含隐式链接信息的应用程序时,系统将应用程序中所有当运行不包含隐式链接信息的应用程序时,系统将应用程序中所有的代码和数据一次性映射到内存中。如果应用程序包含对隐式链接的引的代码和数据一次性映射到内存中。如果应用程序包含对隐式链接的引用,系统则必须

29、先处理引用的信息。系统将应用程序所使用的用,系统则必须先处理引用的信息。系统将应用程序所使用的DLLDLL可执可执行模块映射到进程的地址空间中,修改进程的执行代码,提供行模块映射到进程的地址空间中,修改进程的执行代码,提供DLLDLL函数函数的地址。同应用程序其它代码一样,的地址。同应用程序其它代码一样,DLLDLL代码在应用程序启动时被映射代码在应用程序启动时被映射到内存空间中,并且仅当需要时才装入内存。到内存空间中,并且仅当需要时才装入内存。 6.3.1 6.3.1 隐式链接方式加载隐式链接方式加载DLLDLL 第六章第六章 动态连接库的特点动态连接库的特点当程序启动时,系统首先搜索一组预

30、安装的当程序启动时,系统首先搜索一组预安装的DLLDLL,如性能库,如性能库 (KERNEL32.DLL) (KERNEL32.DLL) 和安全库和安全库 (USER32.DLL)(USER32.DLL),然后按下列顺序搜索,然后按下列顺序搜索 DLLDLL:1)1)当前进程的可执行模块所在的目录。当前进程的可执行模块所在的目录。2)2)当前目录当前目录3)Windows3)Windows系统目录。系统目录。GetSystemDirectory GetSystemDirectory 函数检索此目录的路径。函数检索此目录的路径。4)Windows4)Windows目录。目录。GetWindows

31、Directory GetWindowsDirectory 函数检索此目录的路径。函数检索此目录的路径。5)PATH 5)PATH 环境变量中列出的目录。环境变量中列出的目录。 在启动应用程序时,如果按照以上路径均未能找到所需的在启动应用程序时,如果按照以上路径均未能找到所需的DLLDLL,则,则系统终止程序并报告错误。如果找到所有的系统终止程序并报告错误。如果找到所有的DLLDLL,则,则DLLDLL模块被映射到进模块被映射到进程的内存空间中,进程通过调用程的内存空间中,进程通过调用LibMainLibMain函数与每个函数与每个DLLDLL相连,如果调用相连,如果调用LibMainLibM

32、ain函数失败,程序也将被终止。一旦函数失败,程序也将被终止。一旦DLLDLL被映射到内存中,系统便被映射到内存中,系统便通知应用程序到何处去找它所需要的通知应用程序到何处去找它所需要的DLLDLL函数。函数。6.3.1 6.3.1 隐式链接方式加载隐式链接方式加载DLLDLL 第六章第六章 动态连接库的特点动态连接库的特点下面给出隐式链接的示例:下面给出隐式链接的示例:IMPORTS example.ExportFunction1 IMPORTS example.ExportFunction1 #include #include mainmain()() ExportFunction1();

33、 / ExportFunction1(); /调用动态库中的输出函数调用动态库中的输出函数 I M P O R T SI M P O R T S 语 句 列 出 了 程 序 所 需 要 的语 句 列 出 了 程 序 所 需 要 的 D L LD L L 及 其 函 数及 其 函 数ExportFunction1ExportFunction1,除此之外,程序也可以通过与,除此之外,程序也可以通过与exampleexample的输入的输入库(库(example.libexample.lib)相连来引用)相连来引用DLLDLL函数,这种情况下,函数,这种情况下,IMPORTSIMPORTS语句将被省

34、略。语句将被省略。 6.3.2 6.3.2 显示方式加载显示方式加载DLL DLL 第六章第六章 动态连接库的特点动态连接库的特点 显式链接方式不需要将程序与输入库(显式链接方式不需要将程序与输入库(.Lib.Lib)相连,也不需)相连,也不需要在程序的模块定义文件中使用要在程序的模块定义文件中使用IMPORTSIMPORTS语句来解决对语句来解决对DLLDLL函数的函数的引用,因为程序不以显示的方式调用引用,因为程序不以显示的方式调用DLLDLL函数,因而不产生外部函数,因而不产生外部引用。显式链接方式是指应用程序在运行时,通过引用。显式链接方式是指应用程序在运行时,通过LoadLibrar

35、yLoadLibrary函数显式地加载自己所需的函数显式地加载自己所需的DLLDLL,再用,再用GetProcAddressGetProcAddress函数获取函数获取DLLDLL函数的入口地址,并将该地址赋予函数指针,利用函数指针,函数的入口地址,并将该地址赋予函数指针,利用函数指针,就可以象调用应用程序内部函数一样来调用外部就可以象调用应用程序内部函数一样来调用外部DLLDLL函数了。在函数了。在应用程序结束之前,应该用应用程序结束之前,应该用FreeLibraryFreeLibrary函数来释放动态连接库。函数来释放动态连接库。 6.3.2 6.3.2 显示方式加载显示方式加载DLL D

36、LL 第六章第六章 动态连接库的特点动态连接库的特点显示链接方式所需要的几个主要显示链接方式所需要的几个主要APIAPI函数的定义及说明如下:函数的定义及说明如下:(1 1)加载动态链接库函数)加载动态链接库函数 HMODULE LoadLibrary( LPCTSTRHMODULE LoadLibrary( LPCTSTR lpFileName);lpFileName); lpFileName lpFileName为要载入的动态链接库的名称为要载入的动态链接库的名称 进程调用进程调用 LoadLibraryLoadLibrary以显式链接到以显式链接到 DLLDLL。如果成功,函数将指定的。

37、如果成功,函数将指定的 DLL DLL 映射到调用进程的地址空间中并返回此映射到调用进程的地址空间中并返回此 DLL DLL 的句柄,该句柄可与用于显式链的句柄,该句柄可与用于显式链接的其他函数(如接的其他函数(如 GetProcAddress GetProcAddress 和和 FreeLibraryFreeLibrary)一起使用。)一起使用。LoadLibrary LoadLibrary 尝试使用用于隐式链接的同一搜索序列来定位尝试使用用于隐式链接的同一搜索序列来定位 DLLDLL。如果系统无。如果系统无法找到法找到 DLL DLL 或者入口点函数返回或者入口点函数返回 FALSEFAL

38、SE,LoadLibrary LoadLibrary 将返回将返回 NULLNULL。如果对。如果对 LoadLibrary LoadLibrary 的调用所指定的的调用所指定的 DLL DLL 模块已映射到调用进程的地址空间中,则模块已映射到调用进程的地址空间中,则函数仅返回函数仅返回 DLL DLL 的句柄并递增模块的引用数。的句柄并递增模块的引用数。 如果如果 DLL DLL 有入口点函数(有入口点函数(LibMainLibMain),则操作系统在调用),则操作系统在调用 LoadLibrary LoadLibrary 的进的进程上中调用此函数。如果由于以前调用了程上中调用此函数。如果由

39、于以前调用了 LoadLibrary LoadLibrary 但没有相应地调用但没有相应地调用 FreeLibrary FreeLibrary 函数而导致函数而导致 DLL DLL 已经附加到进程,则不会调用此入口点函数。已经附加到进程,则不会调用此入口点函数。 如果出于某种原因如果出于某种原因 Windows Windows 无法加载无法加载 DLLDLL,进程可以尝试从错误恢复。,进程可以尝试从错误恢复。例如,进程可通知用户所发生的错误,并让用户指定例如,进程可通知用户所发生的错误,并让用户指定 DLL DLL 的其他路径。的其他路径。 6.3.2 6.3.2 显示方式加载显示方式加载DL

40、L DLL 第六章第六章 动态连接库的特点动态连接库的特点(2 2)获取)获取 DLLDLL函数地址函数地址FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName); FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName); hModulehModule:动态链接库句柄动态链接库句柄lpProcName lpProcName :DLLDLL函数名称或输出顺序编号函数名称或输出顺序编号显式链接到显式链接到 DLLDLL的进程调用的进程调用 GetProcAddress G

41、etProcAddress 来获取来获取 DLLDLL输出函数的地输出函数的地址。使用返回的函数指针调用址。使用返回的函数指针调用 DLL DLL 函数。函数。GetProcAddress GetProcAddress 将将DLLDLL模块模块句柄和要调用的函数名或函数的输出序号用作参数。句柄和要调用的函数名或函数的输出序号用作参数。 仅当要链接的仅当要链接的 DLLDLL是用模块定义是用模块定义 (.DEF) (.DEF) 文件生成的,并且序号文件生成的,并且序号在在.DEF.DEF文件的文件的EXPORTSEXPORTS节中与函数一起列出时,才能获取输出序号。如节中与函数一起列出时,才能获

42、取输出序号。如果果 DLL DLL 具有许多输出函数,则相对于使用函数名,使用输出序号调用具有许多输出函数,则相对于使用函数名,使用输出序号调用 GetProcAddress GetProcAddress 的速度稍快一些,因为输出序号是的速度稍快一些,因为输出序号是 DLL DLL 导出表的索引。导出表的索引。使用输出序号,使用输出序号,GetProcAddress GetProcAddress 可直接定位函数,而不是将指定名称可直接定位函数,而不是将指定名称与与 DLL DLL 导出表中的函数名进行比较。但是,仅当有权控制导出表中的函数名进行比较。但是,仅当有权控制 .DEF .DEF 文件

43、文件中导出函数的序号分配时,才应使用输出序号调用中导出函数的序号分配时,才应使用输出序号调用 GetProcAddressGetProcAddress。 6.3.2 6.3.2 显示方式加载显示方式加载DLL DLL 第六章第六章 动态连接库的特点动态连接库的特点(3 3)释放)释放DLLDLLBOOL FreeLibrary( HMODULE hModule ) BOOL FreeLibrary( HMODULE hModule ) /hModule/hModule为动态链接库句柄为动态链接库句柄 不再需要不再需要DLLDLL模块时,显式链接到模块时,显式链接到 DLL DLL 的进程调用的

44、进程调用 FreeLibrary FreeLibrary 函数释放函数释放DLLDLL。此函数递减模块的引用数,如果引用数为零,此函数便。此函数递减模块的引用数,如果引用数为零,此函数便从进程的地址空间中取消模块的映射。下面给出显式链接的示例:从进程的地址空间中取消模块的映射。下面给出显式链接的示例:HANDLE hLibrary;HANDLE hLibrary;FARPROC lpFunc;FARPROC lpFunc;int RetValue;int RetValue;hLibrary=LoadLibrary(example.dll); hLibrary=LoadLibrary(examp

45、le.dll); /加载加载DLLDLLif(hLibrary!=NULL) if(hLibrary!=NULL) /加载成功加载成功 /检取检取ExportFunction1ExportFunction1函数地址,并将地址赋予函数地址,并将地址赋予lpFunclpFunc函数指针函数指针 lpFunc=GetProcAddress(hLibrary,“ExportFunction1”); lpFunc=GetProcAddress(hLibrary,“ExportFunction1”); if(lpFunc!=(FARPROC)NULL) if(lpFunc!=(FARPROC)NULL)

46、/检取成功则调用检取成功则调用 RetValue =(RetValue =(* *lpFunc)(); lpFunc)(); /通过函数指针调用函数通过函数指针调用函数 FreeLibrary(hLibrary); FreeLibrary(hLibrary); /释放占用的内存释放占用的内存 6.4 6.4 动态连接库在网络程序中的应用动态连接库在网络程序中的应用 第六章第六章 动态连接库的特点动态连接库的特点 动态连接库技术存在于动态连接库技术存在于WindowsWindows应用的方方面面,在网络通信中同应用的方方面面,在网络通信中同样也得到了广泛的应用。在样也得到了广泛的应用。在Wind

47、owsWindows下下Windows SocketsWindows Sockets的功能都是通过的功能都是通过动态连接库(动态连接库(DLLDLL)来实现的,因此也常常将)来实现的,因此也常常将Windows SocketsWindows Sockets实现成为实现成为Windows Sockets DLLWindows Sockets DLL(Winsock.dllWinsock.dll)。)。 在一个大型网络程序设计的过程中,往往需要将整个系统划分为若在一个大型网络程序设计的过程中,往往需要将整个系统划分为若干个小的模块,这样有利于小组内部成员的分工与合作。在这些模块中,干个小的模块,这

48、样有利于小组内部成员的分工与合作。在这些模块中,通常将其中的一个模块作为主程序的基本框架或底板,其它模块的功能通常将其中的一个模块作为主程序的基本框架或底板,其它模块的功能以以DLLDLL形式予以实现。程序运行时,框架程序或底板根据需要选择性地形式予以实现。程序运行时,框架程序或底板根据需要选择性地装入所需的装入所需的dlldll。这种开发模式更接近于面向对象的程序设计思想。模。这种开发模式更接近于面向对象的程序设计思想。模块和模块之间更关注于功能,而非技术实现细节。例如为了实现局域网块和模块之间更关注于功能,而非技术实现细节。例如为了实现局域网内两台机器的通信,可以采用内两台机器的通信,可以采用NetBiosNetBios、WinsockWinsock、IPXIPX等多种通信协议,等多种通信协议,程序员可以根据实际情况选择其中的一种通信协议予以实现,

温馨提示

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

评论

0/150

提交评论