动态链接库和静态链接库_第1页
动态链接库和静态链接库_第2页
动态链接库和静态链接库_第3页
动态链接库和静态链接库_第4页
动态链接库和静态链接库_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

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

文档简介

1、 测绘学院:李新维 邮箱: 目目 录录 概念定义概念定义12 静态链接库的创建静态链接库的创建3动态链接库的创建动态链接库的创建4 应用实例应用实例1 1、概念定义、概念定义1.1 1.1 分别编译与链接分别编译与链接 大多数高级语言都支持分别编译(compling),程序员可以显式地把程序划分为独立的模块或文件,然后由编译器(compiler)对每个独立部分分别进行编译。在编译之后,由链接器(Linker)把这些独立编译单元链接(Linking)到一起。 链接方式有两种:静态链接、动态链接。1.2 1.2 链接方式链接方式 静态链接方式静态链接方式:在程序开发中,将各种目标模块(.OBJ)文

2、件、运行时库(.LIB)文件,以及已编译的资源(.RES)文件链接在一起,以便创建Windows的.EXE文件。 动态链接方式动态链接方式:在程序运行时,Windows把一个模块中的函数调用链接到库模块中的实际函数上的过程。1.2 1.2 链接方式链接方式 静态链接库(简称LIB)与动态链接库(简称DLL)都是共享代码的方式。如果使用静态链接库(也称静态库),则无论你愿不愿意,.LIB文件中的指令都会被直接包含到最终生成的.EXE文件中。但是若使用.DLL文件,该.DLL文件中的代码不必被包含在最终的.EXE文件中,.EXE文件执行时可以“动态”地载入和卸载这个与.EXE文件独立的.DLL文件

3、。1.3 1.3 动态链接方式动态链接方式链接一个DLL有两种方式: 1、载入时动态链接(Load-Time Dynamic Linking) 2、运行时动态链接(Run-Time Dynamic Linking) 1.3.1 1.3.1 载入时动态链接载入时动态链接 使用载入时动态链接,调用模块可以像调用本模块中的函数一样直接使用导出函数名调用DLL中的函数。这需要在链接时将函数所在DLL的导入库链接到可执行文件中,导入库向系统提供了载入DLL时所需的信息及用于定位DLL函数的地址符号。(相当于注册,当作API函数来使用,其实API函数就存放在系统DLL当中)。 1.3.2 1.3.2 运行

4、时动态链接运行时动态链接 使用运行时动态链接,运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的入口地址,然后就可以通过返回的函数指针调用DLL中的函数了。如此即可避免导入库文件了。 1.4 1.4 二者优点及不足二者优点及不足静态链接库的优点:(1) 代码装载速度快,执行速度略比动态链接库快; (2) 只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。 1.4 1.4 二者优点及不足二者优

5、点及不足 动态链接库的优点 (1) 更加节省内存并减少页面交换; (2) DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性; (3) 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数。 1.4 1.4 二者优点及不足二者优点及不足不足之处 (1) 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费; (2) 使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给

6、出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败; (3) 使用动态链接库可能造成DLL地狱。 1.4.1 1.4.1 DLL DLL 地狱地狱 DLL 地狱(DLL Hell)是指因为系统文件被覆盖而让整个系统像是掉进了地狱。 简单地讲,DLL地狱是指当多个应用程序试图共享一个公用组件时,如某个DLL或某个组件对象模型(COM)类,所引发的一系列问题。1.4.1 1.4.1 DLL DLL 地狱地狱 最典型的情况是,某个应用程序将要安装一个新版本的共享组件,而该组件与机器上的现有版本不向后兼容。虽然刚安装的应用程序运行正常,但原来依赖前一版本共享

7、组件的应用程序也许已无法再工作。在某些情况下,问题的起因更加难以预料。比如,当用户浏览某些web站点时会同时下载某个Microsoft ActiveX控件。如果下载该控件,它将替换机器上原有的任何版本的控件。如果机器上的某个应用程序恰好使用该控件,则很可能也会停止工作。 在许多情况下,用户需要很长时间才会发现应用程序已停止工作。结果往往很难记起是何时的机器变化影响到了该应用程序。2 2、静态链接库的创建静态链接库的创建2.1 2.1 静态链接库的创建静态链接库的创建 在此通过一个实例来介绍静态库的创建与使用。在该实例中,我们实现将一个两整数相加求和的函数封装到静态库中供其他程序调用。2.1.1

8、 2.1.1 创建一个创建一个Win32Win32控制台应用程序控制台应用程序2.1.2 2.1.2 选择静态库应用程序类型选择静态库应用程序类型2.1.3 2.1.3 新建一个新建一个.h .h文件文件 需要给该静态链接库编写一个声明头文件Static.h,以便在链接时告知编译该链接库中的导出函数声明。Static.h文件中的内容: #ifndef _STATIC_H #define _STATIC_H / 防止该头文件重复引用 extern int Add(int a,int b); / 声明导出函数 #endif2.1.4 2.1.4 新建一个新建一个.cpp.cpp文件文件 添加一个用

9、于定义导出函数的源文件Static.cpp,编码实现两个整数相加的Add函数。源文件代码如下: #includestatic.h int Add(int a,int b) return a+b; 2.1.5 2.1.5 生成生成 点击菜单命令,“工具”-“生成Static”。如果一切顺利的话,就会在解决方案的“Debug”目录中生成了名为“Static.lib”的静态链接库。2.2 2.2 静态链接库的使用静态链接库的使用 新建一个Win32控制台应用程序空项目UseLIB。程序主文件名为UseLIB.cpp,其中包含用于调用Add函数的程序入口函数main。将刚才创建的Static.lib及

10、其声明头文件Static.h一同复制到UseLIB项目目录下。并在源文件UseLIB.cpp中使用预编译命令链接Static.lib(也可以在IDE的项目属性中设置链接器选项,或者只复制Static.h文件并设置UseLIB项目的“项目依赖项”为Static项目)。 2.2 2.2 静态链接库的使用静态链接库的使用源文件UseLIB.cpp中的代码如下:#pragma comment(lib, “Static.lib”) / 链接静态库Static.lib#include #include “Static.h” / 包含Static.lib的声明头文件,声明导出函数Add int main()

11、 int a = 1, b = 2; couta+b=Add(a,b); / 调用Static.lib中的Add函数 return 0; 2.2 2.2 静态链接库的使用静态链接库的使用 接下来点击菜单命令,“工具”-“生成UseLIB”。如果顺利的话,就会在Library解决方案的Debug目录中生成了名为UseLIB.exe的可执行执文件,运行UseLIB.exe,将在控制台中输出结果:1+2=32.3 2.3 注意注意 由于项目中创建的源文件为.CPP文件,即C+源文件,因此Visual C+按C+规范,并采用_cdecl调用约定对其进行编译。这样得到的导出函数就不能被C语言程序所调用。

12、解决该问题的办法是在函数体名称前添加extern “C”修饰,告诉编译器,该函数按照C语言规范,并采用_cdecl调用约定进行编译。因此源文件Add.cpp中的代码可修改如下:extern “C” int add(int a, int b)最后重新编译该静态链接库项目,导出函数Add就能够被C语言程序所调用了。3 3、动、动态链接库的创建态链接库的创建3.1 3.1 动态链接库的创建动态链接库的创建 在此同样通过一个实例来介绍动态链接库的创建与使用。在实例中,依然使用Add函数进行讲解,这样一方面可以沿用上面静态链接的有关内容,另一方面也可以了解动态链接库与静态链接库在创建和使用上的异同。3.

13、1.1 3.1.1 创建一个创建一个Win32Win32控制台应用程序控制台应用程序3.1.2 3.1.2 选择静态库应用程序类型选择静态库应用程序类型3.1.3 3.1.3 新建一个新建一个.h .h文件文件 编写一个声明头文件Dynamic.h,以便在以后链接时告知编译器该链接库中的具体的导入内容(一般包括代码和资源)。Dynamic.h: ifndef _DYNAMIC_H_ / 防止该头文件重复引用 #define _DYNAMIC_H_ extern C _declspec(dllexport) int Add(int a, int b); / 声明导出函数 #endif3.1.4

14、3.1.4 新建一个新建一个.cpp.cpp文件文件 用于定义导出函数的源文件Dynamic.cpp,编码实现两个整数相加的Add函数。extern “C” _declspec(dllexport) int Add(int a, int b) / 声明为DLL导出函数 return a + b; 3.1.4 3.1.4 生成生成 点工具栏上的生成按钮,则可以在debug下生成:2.2 2.2 动态链接库的使用动态链接库的使用 1、载入时动态链接、载入时动态链接 2、运行时动态链接、运行时动态链接2.2.1 2.2.1 载入时动态链接载入时动态链接 将导入库Dynamic.lib及其声明头文件D

15、ynamic.h一同复制到UseDLL项目目录下,并把Dynamic.dll复制到项目的Debug目录中。并在源文件UseDLL.cpp中使用预编译命令链接Dynamic.lib(也可以在IDE的项目属性中设置链接器选项)。 源文件源文件UseDLL.cpp中的代码如下:中的代码如下:#pragma comment(lib, “Dynamic.lib”) / 链接导入库Dynamic.lib #include #include “Dynamic.h” / 声明头文件,提供导出函数Add的声明 int main() int a = 1, b = 2; couta+b=Add(a,b); / 调用

16、Dynamic.DLL中的Add函数 return 0;2.2.1 2.2.1 运行时动态链接运行时动态链接 运行时动态链接的代码相对麻烦些,需要使用到Windows的三个API函数,还要进行一些判断以防止不必要的麻烦。我们在UseDLL项目的基础上做些修改来实现运行时动态链接。这里只需要把Dynamic.dll复制到UseDLL项目的Debug目录中,因为不用在编译的时候链接导入库,只要在运行根据需要链接Dynamic.dll。2.2.1 2.2.1 运行时动态链接运行时动态链接 下面先给出修改后的源文件Dynamic.cpp的代码:#include / 用于声明window API函数及宏

17、等#includetypedef int (* FuncAdd)(int a, int b); / 定义将要调用的导出函数Add的指针类型 int main() FuncAdd Add; / 定义Add函数指针 int a = 1, b = 2; HMODULE hDLL = LoadLibrary(TEXT(MyDLL.dll); / 载入DLL,并获取其句柄 if (hDLL) / MyDLL.dll载入成功 Add = (FuncAdd)GetProcAddress(hDLL, Add); / 获取导出函数Add指针 if (Add) / 正确获取Add函数指针 couta+b=Add(

18、a,b); / 调用导出函数Add else / 没有找到Add函数 coutAdd Not Found!n; else / MyDLL.dll载入失败 coutLoadLibrary Failed!n; FreeLibrary(TEXT(MyDLL.dll); / 释放DLL return 0; 2.2.1 2.2.1 运行时动态链接运行时动态链接 由于没有链接导入库,不能使用地址符号定位导出函数的入口地址,只能通过GetProcAdress来获取其在地址空间中的指针,再通过指针调用。但程序在运行之前,GetProcAdress无法判断指针的有效性。因此,为了防止Dynamic项目中不存在Add函数而

温馨提示

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

评论

0/150

提交评论