一、DLL库与LIB库对比:
静态连接库Lib(Static Link Library),是在编译的连接阶段将库函数嵌入到应用程序的内部。若是系统中运行的多个应用程序都包含所用到的公共库函数,则必然形成很大的浪费。这样即增长了连接器的负担,也增大了可执行程序的大小,还加大了内存的消耗。Lib的好处是应用程序能够独立运行,而不须要在操做系统中另外安装对应的DLL。html
而DLL采用动态连接,对公用的库函数,系统只有一个拷贝(通常是位于系统目录的*.DLL文件),并且只有在应用程序真正运行阶段调用时,才加载到内存。在内存中的库函数,也只有一个拷贝,可供全部运行的程序调用。当再也没有程序须要调用它时,系统会自动将其卸载,并释放其所占用的内存空间。DLL的缺点是应用程序不能独立运行,须要在操做系统中另外安装对应的DLL。例如,若是你的MFC项目被设置成“在共享DLL中使用MFC”的,则虽然生成的可执行程序很小,可是在其余没有安装Visual C++(运行环境)的机器上是不能直接运行的,须要另外安装MFC的动态连接库(如mfc90.dll)。ios
二、DLL库与LIB库区别:
(1)lib是编译时用到的,dll是运行时用到的。
(2)若是有dll文件,那么lib的大小会很小,通常是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;若是只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不须要再挂动态库,缺点是致使应用程序比较大,失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。windows
(3)动态连接的状况下,有两个文件:一个是LIB文件,一个是DLL文件。连接方式也相应的可分为:隐式连接和显式连接。LIB包含被DLL导出的 函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件连接到DLL文件。隐式连接时,在应用程序的可执行文件中,存放的不是被调用的函数代码,而是 DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一块儿发行,不然应用程序会产生错误。显式连接时,若是不想用lib文件或者没有 lib文件,能够用WIN32 API函数LoadLibrary、GetProcAddress装载。安全
三、DLL库与LIB库的调用方法:
使用LIB库的方法:
静态lib中,一个lib文件其实是任意个obj文件的集合,obj文件是cpp文件编译生成的。在编译这种静态库工程时,根本不会遇到连接错误;即便有错,也只会在使用这个lib的EXT文件或者DLL工程里暴露出来。
在VC中新建一个static library类型的工程Lib,加入test.cpp文件和test.h文件(头文件内包括函数声明),而后编译,就生成了Lib.lib文件。
别的工程要使用这个lib有两种方式:
(1)在project->link->Object/Library Module中加入Lib.lib文件(先查询工程目录,再查询系统Lib目录);或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)。
(2)将Lib.lib拷入工程所在目录,或者执行文件生成的目录,或者系统Lib目录中。
(3)加入相应的头文件test.h。
使用DLL库的方法:
使用动态连接中的lib,不是obj文件的集合,即里面不会有实际的实现,它只是提供动态连接到DLL所须要的信息(包括DLL响应函数的信息、地址等),这种lib能够在编译一个DLL工程时由编译器自动生成。
(1)隐式连接
第 一种方法是:经过project->link->Object/Library Module中加入.lib文件(或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)),并将.dll文件置入工程所在目录,而后添加对应的.h头文件。函数











(2)显式连接
须要函数指针和WIN32 API函数LoadLibrary、GetProcAddress装载,使用这种载入方法,不须要.lib文件和.h头文件,只须要.dll文件便可(将.dll文件置入工程目录中)。spa
























四、MFC中DLL中函数的导出方法
使用MFC建立DLL时,从项目中导出(export)函数到DLL文件的方法有:操作系统
(1) 使用模块定义文件(.def)。命令行
(2)使用__declspec(dllexport)关键字或其替代宏AFX_EXT_CLASS。指针
这两种方法是互斥的,对每一个函数只需用一种方法便可。另外,DEF文件只能用来导出函数,不能用于导出整个类。导出C++类,必须用__declspec(dllexport)关键字或其替代宏AFX_EXT_CLASS。htm
DEF文件
模块定义(module definition)文件(.def)是包含一个或多个描述DLL各类属性的模块语句的文本文件。DEF文件必须至少包含下列模块定义语句:
文件中的第一个语句必须是LIBRARY语句。此语句将.def文件标识为属于DLL。LIBRARY语句的后面是DLL的名称(缺省为DLL项目名)。连接器将此名称放到DLL的导入库中。
EXPORTS语句列出名称,可能的话还会列出DLL导出函数的序号值。经过在函数名的后面加上@符和一个数字,给函数分配序号值。当指定序号值时,序号值的范围必须是从1到N,其中N是DLL导出函数的个数。
即,DEF文件的格式为:(在这两个语句之间,还能够加上可选的描述语句:DESCRIPTION "库描述串"。分号;后的文本内容行为注释)
库名.def
LIBRARY 库名
EXPORTS
函数名1 @1
函数名2 @2
……
函数名n @n
在使用MFC DLL向导建立MFC DLL项目时,VC会自动建立一个与项目同名但没有任何函数导出项的DEF文件(项目名.def),格式为:
项目名.def : 声明 DLL 的模块参数。
LIBRARY "项目名"
EXPORTS
。。。
例如,项目名为RegDll的DEF文件(RegDll.def)的内容为:
; RegDll.def : 声明 DLL 的模块参数。
LIBRARY "RegDll"
EXPORTS
。。。
当生成DLL时,连接器使用.def文件建立导出(.exp)文件和导入库(.lib)文件。而后,连接器使用导出文件生成DLL文件。隐式连接到DLL的可执行文件在生成时连接到导入库。请注意,MFC自己就是使用.def文件从MFCx0.dll导出函数和类的。
关键字或宏
除了使用DEF文件来导出函数外,还能够在源程序中使用__declspec(dllexport)关键字或其替代宏AFX_EXT_CLASS:
#define AFX_EXT_CLASS AFX_CLASS_EXPORT (定义在头文件afxv_dll.h中)
#define AFX_CLASS_EXPORT __declspec(dllexport) (定义在头文件afxver_.h中)
来导出函数和整个C++类。
具体的格式为:
导出整个类:
class AFX_EXT_CLASS 类名[ : public基类]
{
……
}
导出类的成员函数:
class 类名[ : public基类]
{
AFX_EXT_CLASS 返回类型 函数名1(……) ;
AFX_EXT_CLASS 返回类型 函数名2(……) ;
……
}
导出外部C格式的(全局)函数:
extern "C" __declspec(dllexport) 返回类型 函数名(……)
{
……
}
若是但愿用MFC(C++)编写的规则DLL中的函数,也可以被非MFC程序来调用,须要为函数声明指定extern "C"。否则,C++编译器会使用C++类型安全命名约定(也称做名称修饰)和C++调用约定(使用此调用约定从C调用会很困难)。
为了使用方便,能够定义宏:
#define DllExport extern "C" __declspec(dllexport)
而后再使用它,例如:
DllExport int Add(int d1, int d2) {……}
五、VC查找DLL及LIB库的目录优先顺序
为了使须要动态连接库的应用程序能够运行,须要将库文件放在操做系统可以找到的地方。Windows操做系统查找库的目录顺序为:
- 所在目录——当前进程的可执行模块所在的目录,即应用程序的可执行文件(*.exe)所在的目录。
- 当前目录——进程的当前目录。
- 系统目录——Windows操做系统安装目录的系统子目录,如C:\Windows\ System32。可用GetSystemDirectory函数检索此目录的路径。
- Windows目录——Windows操做系统安装目录,如C:\Windows\。可用GetWindowsDirectory函数检索此目录的路径。
- 搜索目录——PATH环境变量中所包含的自动搜索路径目录,通常包含C:\Windows\和C:\Windows\System32\等目录。可在命令行用Path命令来查看和设置,也能够经过(在“个人电脑”右键菜单中选“属性”菜单项)“系统属性”中的环境变量,来查看或编辑“Path”系统变量和“PATH”用户变量。
参考:https://www.cnblogs.com/405845829qq/p/4108450.html
参考:https://www.cnblogs.com/19910101zj/p/4611695.html