《动态链接库和静态链接库.ppt》由会员分享,可在线阅读,更多相关《动态链接库和静态链接库.ppt(43页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、静静态链接接库和和动态链接接库 测绘学院:李新维 邮箱:目目 录录 概念定义概念定义12 静态链接库的创建静态链接库的创建3动态链接库的创建动态链接库的创建4 应用实例应用实例1、概念定义1.1分别编译与链接大多数高级语言都支持分别编译(compling),程序员可以显式地把程序划分为独立的模块或文件,然后由编译器(compiler)对每个独立部分分别进行编译。在编译之后,由链接器(Linker)把这些独立编译单元链接(Linking)到一起。链接方式有两种:静态链接、动态链接。1.2链接方式静静态链接方式接方式:在程序开发中,将各种目标模块(.OBJ)文件、运行时库(.LIB)文件,以及已编
2、译的资源(.RES)文件链接在一起,以便创建Windows的.EXE文件。动态链接方式接方式:在程序运行时,Windows把一个模块中的函数调用链接到库模块中的实际函数上的过程。1.2链接方式静态链接库(简称LIB)与动态链接库(简称DLL)都是共享代码的方式。如果使用静态链接库(也称静态库),则无论你愿不愿意,.LIB文件中的指令都会被直接包含到最终生成的.EXE文件中。但是若使用.DLL文件,该.DLL文件中的代码不必被包含在最终的.EXE文件中,.EXE文件执行时可以“动态”地载入和卸载这个与.EXE文件独立的.DLL文件。1.3动态链接方式链接一个DLL有两种方式:1、载入时动态链接(
3、Load-TimeDynamicLinking)2、运行时动态链接(Run-TimeDynamicLinking)1.3.1载入时动态链接使用载入时动态链接,调用模块可以像调用本模块中的函数一样直接使用导出函数名调用DLL中的函数。这需要在链接时将函数所在DLL的导入库链接到可执行文件中,导入库向系统提供了载入DLL时所需的信息及用于定位DLL函数的地址符号。(相当于注册,当作API函数来使用,其实API函数就存放在系统DLL当中)。1.3.2运行时动态链接使用运行时动态链接,运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetP
4、rocAddress获取DLL函数的入口地址,然后就可以通过返回的函数指针调用DLL中的函数了。如此即可避免导入库文件了。1.4二者优点及不足静态链接库的优点:(1)代码装载速度快,执行速度略比动态链接库快;(2)只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。1.4二者优点及不足动态链接库的优点(1)更加节省内存并减少页面交换;(2)DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和
5、可扩展性;(3)不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数。1.4二者优点及不足不足之处(1)使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费;(2)使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败;(3)使用动态链接库可能造成DLL地狱。1.4.1DLL地狱DLL地狱(DLLHell)是指因为系统文件被覆盖而让整个系统像是掉进了地狱。简单地讲,DLL地狱是指当多个应用程
6、序试图共享一个公用组件时,如某个DLL或某个组件对象模型(COM)类,所引发的一系列问题。1.4.1DLL地狱最典型的情况是,某个应用程序将要安装一个新版本的共享组件,而该组件与机器上的现有版本不向后兼容。虽然刚安装的应用程序运行正常,但原来依赖前一版本共享组件的应用程序也许已无法再工作。在某些情况下,问题的起因更加难以预料。比如,当用户浏览某些web站点时会同时下载某个MicrosoftActiveX控件。如果下载该控件,它将替换机器上原有的任何版本的控件。如果机器上的某个应用程序恰好使用该控件,则很可能也会停止工作。在许多情况下,用户需要很长时间才会发现应用程序已停止工作。结果往往很难记起
7、是何时的机器变化影响到了该应用程序。2、静态链接库的创建2.1静态链接库的创建在此通过一个实例来介绍静态库的创建与使用。在该实例中,我们实现将一个两整数相加求和的函数封装到静态库中供其他程序调用。2.1.1创建一个Win32控制台应用程序2.1.2选择静态库应用程序类型2.1.3新建一个.h文件需要给该静态链接库编写一个声明头文件Static.h,以便在链接时告知编译该链接库中的导出函数声明。Static.h文件中的内容:#ifndef_STATIC_H#define_STATIC_H/防止该头文件重复引用externintAdd(inta,intb);/声明导出函数#endif2.1.4新建
8、一个.cpp文件添加一个用于定义导出函数的源文件Static.cpp,编码实现两个整数相加的Add函数。源文件代码如下:#includestatic.hintAdd(inta,intb)returna+b;2.1.5生成点击菜单命令,“工具”-“生成Static”。如果一切顺利的话,就会在解决方案的“Debug”目录中生成了名为“Static.lib”的静态链接库。2.2静态链接库的使用新建一个Win32控制台应用程序空项目UseLIB。程序主文件名为UseLIB.cpp,其中包含用于调用Add函数的程序入口函数main。将刚才创建的Static.lib及其声明头文件Static.h一同复制到
9、UseLIB项目目录下。并在源文件UseLIB.cpp中使用预编译命令链接Static.lib(也可以在IDE的项目属性中设置链接器选项,或者只复制Static.h文件并设置UseLIB项目的“项目依赖项”为Static项目)。2.2静态链接库的使用源文件UseLIB.cpp中的代码如下:#pragmacomment(lib,“Static.lib”)/链接静态库Static.lib#include#include“Static.h”/包含Static.lib的声明头文件,声明导出函数Addintmain()inta=1,b=2;couta+b=Add(a,b);/调用Static.lib中的
10、Add函数return0;2.2静态链接库的使用接下来点击菜单命令,“工具”-“生成UseLIB”。如果顺利的话,就会在Library解决方案的Debug目录中生成了名为UseLIB.exe的可执行执文件,运行UseLIB.exe,将在控制台中输出结果:1+2=32.3注意由于项目中创建的源文件为.CPP文件,即C+源文件,因此VisualC+按C+规范,并采用_cdecl调用约定对其进行编译。这样得到的导出函数就不能被C语言程序所调用。解决该问题的办法是在函数体名称前添加extern“C”修饰,告诉编译器,该函数按照C语言规范,并采用_cdecl调用约定进行编译。因此源文件Add.cpp中的
11、代码可修改如下:extern“C”intadd(inta,intb)最后重新编译该静态链接库项目,导出函数Add就能够被C语言程序所调用了。3、动态链接库的创建3.1动态链接库的创建在此同样通过一个实例来介绍动态链接库的创建与使用。在实例中,依然使用Add函数进行讲解,这样一方面可以沿用上面静态链接的有关内容,另一方面也可以了解动态链接库与静态链接库在创建和使用上的异同。3.1.1创建一个Win32控制台应用程序3.1.2选择静态库应用程序类型3.1.3新建一个.h文件编写一个声明头文件Dynamic.h,以便在以后链接时告知编译器该链接库中的具体的导入内容(一般包括代码和资源)。Dynami
12、c.h:ifndef_DYNAMIC_H_/防止该头文件重复引用#define_DYNAMIC_H_externC_declspec(dllexport)intAdd(inta,intb);/声明导出函数#endif3.1.4新建一个.cpp文件用于定义导出函数的源文件Dynamic.cpp,编码实现两个整数相加的Add函数。extern“C”_declspec(dllexport)intAdd(inta,intb)/声明为DLL导出函数returna+b;3.1.4生成点工具栏上的生成按钮,则可以在debug下生成:2.2动态链接库的使用1 1、载入入时动态链接接 2 2、运行、运行时动态链
13、接接2.2.1载入时动态链接将导入库Dynamic.lib及其声明头文件Dynamic.h一同复制到UseDLL项目目录下,并把Dynamic.dll复制到项目的Debug目录中。并在源文件UseDLL.cpp中使用预编译命令链接Dynamic.lib(也可以在IDE的项目属性中设置链接器选项)。源文件源文件UseDLL.cppUseDLL.cpp中的代中的代码码如下:如下:#pragmacomment(lib,“Dynamic.lib”)/链接导入库Dynamic.lib#include#include“Dynamic.h”/声明头文件,提供导出函数Add的声明intmain()inta=1
14、,b=2;couta+b=Add(a,b);/调用Dynamic.DLL中的Add函数return0;2.2.1运行时动态链接运行时动态链接的代码相对麻烦些,需要使用到Windows的三个API函数,还要进行一些判断以防止不必要的麻烦。我们在UseDLL项目的基础上做些修改来实现运行时动态链接。这里只需要把Dynamic.dll复制到UseDLL项目的Debug目录中,因为不用在编译的时候链接导入库,只要在运行根据需要链接Dynamic.dll。2.2.1运行时动态链接下面先给出修改后的源文件Dynamic.cpp的代码:#include/用于声明windowAPI函数及宏等#includet
15、ypedefint(*FuncAdd)(inta,intb);/定义将要调用的导出函数Add的指针类型intmain()FuncAddAdd;/定义Add函数指针inta=1,b=2;HMODULEhDLL=LoadLibrary(TEXT(MyDLL.dll);/载入DLL,并获取其句柄if(hDLL)/MyDLL.dll载入成功Add=(FuncAdd)GetProcAddress(hDLL,Add);/获取导出函数Add指针if(Add)/正确获取Add函数指针couta+b=Add(a,b);/调用导出函数Addelse/没有找到Add函数coutAddNotFound!n;else/
16、MyDLL.dll载入失败coutLoadLibraryFailed!n;FreeLibrary(TEXT(MyDLL.dll);/释放DLLreturn0;2.2.1运行时动态链接由于没有链接导入库,不能使用地址符号定位导出函数的入口地址,只能通过GetProcAdress来获取其在地址空间中的指针,再通过指针调用。但程序在运行之前,GetProcAdress无法判断指针的有效性。因此,为了防止Dynamic项目中不存在Add函数而使程序在运行时出错,有必要在调用Add之前判断其函数指针的有效性。4、应用动态链接库的应用举例(1)所有的Windows系统调用(WindowsAPI函数)都是以
17、动态链接库的 形式提供的。我们在Windows目录下的system32文件夹中会看到kernel32.dll、user32.dll和gdi32.dll,windows的大多数API都包含在这些DLL中。kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。与这些动态库相对应的导入库分别为kernel32.lib、user32.lib和gdi32.lib。(2)软件插件技术。许多Windows应用软件都支持插件扩展方式,如IE浏览器、Photoshop、Office等等。插件在本质上都是动态库。动态链接库的应用举例(3)软件的自动更新。Windows应用的开发者常常利用动态链接库来分发软件更新。他们生成一个动态库的新版本,然后用户可以下载,并用它替代当前的版本。当然,新、旧版本动态库的输出接口(即导出函数)必须一致。下一次用户运行应用程序时,应用将自动链接和加载新的动态库。(4)可扩展的Web服务器。(5)每个Windows驱动程序在本质上都是动态链接库。谢谢!