`
huozheleisi
  • 浏览: 1234258 次
文章分类
社区版块
存档分类
最新评论

静态链接库LIB和动态链接库DLL的区别

 
阅读更多

静态链接库LIB和动态链接库DLL的区别

一、静态链接库与动态链接库区别

静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都全部被直接包含在最终生成的EXE文件中了。但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。

静态链接库与静态链接库调用规则总体比较如下:

1、静态链接库(比较简单)

首先,静态链接库的使用需要库的开发者提供生成库的.h头文件和.lib文件。生成库的.h头文件中的声明格式如下:

extern "C"函数返回类型函数名(参数表);

在调用程序的.cpp源代码文件中如下:

#include "../lib.h"

#pragma comment(lib,"..//debug//libTest.lib")//指定与静态库一起链接

其次因为静态链接库是将全部指令都包含入调用程序生成的EXE文件中。因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况,要想用就得全要!要不就都别要!

2、态链接库:

动态链接库的使用需要库的开发者提供生成的.lib文件和.dll文件。或者只提供dll文件。

首先我们必须先注意到DLL内的函数分为两种:

1)出函数,可供应用程序调用;

2)LL内部函数,只能在DLL程序使用,应用程序无法调用它们。

因此调用程序若想调用DLL中的某个函数就要以某种形式或方式指明它到底想调用哪一个函数。

Ø对于DLL的导出,可以采用如下方法:

#ifdef WLL_EXPORTS

#define WLL_API __declspec(dllexport)

#else

#define WLL_API __declspec(dllimport)

#endif

这是导出类的宏定义,将导出类必须加上该宏,才能被导出。

此处的WLL_EXPORTS会出现在projectàsettingsàC++àPreProcessorPreProcessor definition中,这个MACRO表明其要定义一个导出宏。

当前库编译时,加了WLL_API的类将被导出,而包含该头文件的其他调用DLLEXE,由于没有定义WLL_API宏,将申明为导入该类。

Ø动态库函数的调用,可以采用静态链接的方式,主要步骤如下:

1)包含DLL中导出的头文件。

2)采用#pragma comment(lib,"..//debug//libTest.lib")导入动态库生成的*.lib头文件。或在projectàsettingsàLinkeràInputAdditional Dependencies中加入lib文件。

3)将动态库生成的*.dll文件放到EXEDLL的同一目录下。

Ø也可以采用动态加载的方式调用,步骤如下:

Another.dll有一个int Add(int x,int y)函数。则完整的调用过程如下:

typedef int (* FunPtr)(int,int);//定义函数指针

FunPtr funPtr;

Handle handle =LoadLibrary("Another.dll");

funPtr =FunPtrGetProcAddress(handle ,"Add");

funPtr(2,3);// 2+3;

FreeLibrary(handle);//释放载入的动态库

二、LIB文件

目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称静态库”),另一种为动态连接库(DLL,以下简称动态库”)的导入库(Import Libary,以下简称导入库)。

静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。

动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。

导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

这也是实际上很多开源代码发布的惯用方式:

1、预编译的开发包:包含一些.dll文件和一些.lib文件。其中这里的.lib就是导入库,而不要错以为是静态库。但是引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时,就会自动调入动态链接库。

2、用户自己编译:下载的是源代码,按照readme自己编译。生成很可能也是.dll + .lib(导入库)的库文件

3、如果你只有dll,并且你知道dll中函数的函数原型,那么你可以直接在自己程序中使用LoadLibary调入DLL文件,GetProcAddress获取函数地址,然后调用。

三、DLL文件

动态链接库(DLL)是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL副本的内容。

动态链接与静态链接的不同之处在于它允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位DLL函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。

使用动态链接代替静态链接有若干优点。DLL节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展MFC库类的机制,支持多语言程序,并使国际版本的创建轻松完成。

API就是应用程序编程接口。它是能用来操作组件、应用程序或者操作系统的一组函数。典型的情况下,API由一个或多个提供某种特殊功能的DLL组成。

DLL是一个文件,其中包含了在Microsoft Windows下运行的任何应用程序都可调用的函数。运行时,DLL中的函数动态地链接到调用它的应用程序中。无论有多少应用程序调用DLL中的某个函数,在磁盘上只有一个文件包含该函数,且只在它调入内存时才创建该DLL您听到最多的API可能是Windows API,它包括构成Windows操作系统的各种DLL。每个Windows应用程序都直接或间接地与Windows API互动。Windows API保证Windows下运行的所有应用程序的行为方式一致。

随着Windows操作系统的发展,现已发布了几个版本的Windows APIWindows 3.1使用Win16 APIMicrosoft Windows NTWindows 95Windows 98平台使用Microsoft Win32 API。除Windows API外,其他一些API也已发布。例如,邮件应用程序编程接口(MAPI)是一组可用于编写电子邮件应用程序的DLLAPI传统上是为开发Windows应用程序的CC++程序员编写的,但其他的编程语言(包括VBA)也可以调用DLL中的函数。因为大部分DLL主要是为CC++程序员编写和整理说明的,所以调用DLL函数的方法与调用VBA函数会有所不同。在使用API时必须了解如何给DLL函数传递参数。

警告:调用Windows API其他DLL函数可能会给您的应用程序带来不良影响。从自己的代码中直接调用DLL函数时,您绕过了VBA通常提供的一些安全机制。如果在定义或调用DLL函数时出现错误(所有程序员都不可避免),可能会在应用程序中引起应用程序错误(也称为通用性保护错误,或GPF)。最好的解决办法是在运行代码以前保存该项目,并确保了解DLL函数调用的原理。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics