C++动态链接库(DLL)的创建和调用
一、什么是库
我们在编写C/C++等语言程序的时候,经常会遇到很多反复使用的或者常用的部分,如果没次都重新编写代码是一件十分麻烦且无意义的事情,会严重影响我们的工作效率以及代码的可读性,并且无法在其他项目重复使用我们的代码。因此我们可以将函数代码封装成一个库文件,方便其他项目的调用。
二、动态库和静态库
静态库和动态库从字面意思来看,区别就是静态和动态。而这里的静态和动态指的是库的链接阶段。可以看如下的编译过程。
静态库:在链接阶段库将会与目标汇编后的目标文件.o一起打包生成可执行文件。成为可执行文件的一部分,后续此库就可以消失了。也就是说在编译的最后一步(链接阶段),如果程序需要使用静态库,在这一步都会一起打包到可执行文件中。
优点:
1、 使可执行文件依赖项少,已经被打包到可执行文件中了
2、 编译阶段完成链接,执行期间代码装载速度快
缺点:
1、使可执行文件变大
2、若作为其他库的依赖库,将会造成多余的副本,因为必须与目标文件打包
3、升级不方便,升级必须重新编译
动态库:而动态库在编译阶段都不会有什么动作,只有在程序运行时才被加载,也就是动态库的链接是发生在程序运行时期的,它和可执行文件是分开的,只是可执行文件在运行的某个时期调用了它。
优点:
1、动态库可以实现进程之间资源共享,有一份就行。
2、升级程序简单,不需要重新编译。
缺点:
1、运行期间在加载,将会减慢代码执行速度。
2、增加程序的依赖项,必须跟着可执行文件一起。
三、动态链接库(DLL)的创建
1>>打开Visual Studio选择创建新项选择动态链接库(DLL),点击下一步
2>>配置项目名称点击创建
3>>分别创建用于声明和定义函数的头文件.h和源文件.cpp
4>>在头文件中定义我们的函数
指定符号的导入导出:
MSVC编译器提供了一系列C/C++的扩展来指定符号的导入导出,即__declspec属性关键字。
__declspec(dllexport) 表示该符号是从本DLL导出的符号。
__declspec(dllimport) 表示该符号是从别的DLL中导入的。
因此我们可以用一个一个宏来定义我们的导出导入关键字,如果定义了宏就设置了__declspec(dllexport)修饰符,若未定义则设置__declspec(dllimport)。
现在我们头文件中一个用于加法和减法的函数并加上宏定义的修饰符,以及声明一个需要导出的类的函数。
在我们创建的.cpp文件中包含我们的.h头文件并且实现我们的函数
5>>生成解决方案
声明并且实现完我们的代码后,点击生成解决方案
在我们的Debug目录下可以看到我们生成的dll文件以及一个lib文件。
到现在我们的动态库就创建完成了,接下来就是在一个新项目中调用我们的动态库了。
四、动态链接库(DLL)的调用
加载动态库有两种方式,分为隐式加载和显示加载。
隐式加载:所需文件:接口.h头文件,dll文件,lib文件。.h和.lib加载方式与静态加载完全一致。但.dll文件必须放在环境变量指定的目下。当然通常是与目标.exe文件放在一起。
显式加载:所需文件:dll文件。利用LoadLibrary()函数进行加载。
下面介绍一下常用的隐式加载的方法。
1>>首先创建一个用于测试的空项目
2>>隐式链接采用静态加载的方式,需要将创建的.dll文件以及.lib文件还有定义的.h头文件,拷贝至我们需要测试的新项目的目录下。
3>>将拷贝的头文件添加到空白项目中
4>>在属性—链接器—输入—附加依赖项中添加我们拷贝过来的.lib文件
5>>创建一个.cpp源文件开始进行我们动态库的调用,包含头文件后直接可以调用我们封装的函数
6>>查看调用后的结果
到现在已经成功的创建了我们的动态链接库dll,并且调用成功!