动态链接库Dynamic-Linked Lib 的创建与使用
动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。这些库函数的扩展名是 ”.dll"。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 文件中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。使用动态链接库可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,您有一个大型网络游戏,如果把整个数百MB甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库中,您无需重新生成或安装整个程序就可以应用更新。;系统中常常是 ".so" 的文件表示是动态链接库。
- 扩展了应用程序的特性;
- 可以用许多种编程语言来编写;
- 简化了软件项目的管理;
- 有助于节省内存;
- 有助于资源共享;
- 有助于应用程序的本地化;
- 有助于解决平台差异;
- 可以用于一些特殊的目的。Windows 使得某些特性只能为 DLL 所用。
VS2013在创建DLL时提供了很好的便捷性,通过新建项目--Win32项目: 选中DLL,以及导出符号,则MFC会自动生成Win32Dll2.h和Win32Dll2.cpp 两个文件,.h文件是要导出内容的声明文件,可以直接和DLL文件一起发送公开。如下图:
修改.cpp文件中按照给出的实例添加自己的程序:
可以在DLL中添加:变量,函数,类
1 // Win32Dll2.cpp : 定义 DLL 应用程序的导出函数。 2 // 3 #include "stdafx.h" 4 #include "Win32Dll2.h" 5 // 这是导出变量的一个示例 6 WIN32DLL2_API int nWin32Dll2=0; 7 // 这是导出函数的一个示例。 8 WIN32DLL2_API int fnWin32Dll2(void) 9 {10 return 42;11 }12 // 这是已导出类的构造函数。13 // 有关类定义的信息,请参阅 Win32Dll2.h14 CWin32Dll2::CWin32Dll2()15 {16 return;17 }18 WIN32DLL2_API int addByDll(int a, int b)19 {20 return a + b;21 }
修改.h文件,添加自己函数的dll声明:
1 // 下列 ifdef 块是创建使从 DLL 导出更简单的 2 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 WIN32DLL2_EXPORTS 3 // 符号编译的。在使用此 DLL 的 4 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 5 // WIN32DLL2_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 6 // 符号视为是被导出的。 7 #ifdef WIN32DLL2_EXPORTS 8 #define WIN32DLL2_API __declspec(dllexport) 9 #else10 #define WIN32DLL2_API __declspec(dllimport)11 #endif12 13 // 此类是从 Win32Dll2.dll 导出的14 class WIN32DLL2_API CWin32Dll2 {15 public:16 CWin32Dll2(void);17 // TODO: 在此添加您的方法。18 19 };20 extern WIN32DLL2_API int nWin32Dll2;21 WIN32DLL2_API int fnWin32Dll2(void);22 WIN32DLL2_API int addByDll(int a, int b);
编译Win32Dll2项目,在编译C++DLL之前,需要做以下配置(项目右键项目属性):项目属性--[C/C++]--高级:修改“编译为”的值为"C++",这样创建C++调用的动态DLL。
则再解决方案的Debug目录下面生成如下文件:其中.dll文件,以及.lib文件最重要 。
.dll文件最终要放在被调用项目的Debug目录下面(随exe文件同目录位置)。
.lib文件需要包含如被调用项目中。
.h文件也提供给用户,用于包含在被调用项目的文件目录中。因为一般DLL会提供一个头文件,在此文件中提供DLL导出函数原型的声明.h文件。这样便于DLL方便调用。
DLL库的使用:
创建DLL测试工程:dllTest, Win32控制台项目
使用DLL步骤如下:
(1)将DLL提供的头文件XXX.h放置在测试项目中的物理文件存储位置。
在测试项目中将此文件包含进来:在放置的合适的逻辑位置右键--添加--已有文件,添加即可。
或者:1.当不需要模块划分,直接放置在了测试项目文件根目录下面:
相对路径方式:再使用的文件中直接#include“..\..XXX.h”。 直接调用。(需要考虑相对路径问题)
或者:2. 当需要模块划分,文件放置在项目文件根目录中下的子模块的文件夹下面:
修改“附加包含目录”:项目属性--配置属性--【C/C++】--常规:附加包含目录。 即添加.h文件所在的目录。 然后直接在需要使用的文件中#include“XXX.h”,从而不需要考虑相对路径的问题。
(2)将DLL提供的XXX.lib文件添加到测试项目中。
1. 添加文件引用的lib静态库路径:
修改“附加包含目录”:项目属性--配置属性--连接器--常规:附加库目录。 即添加.lib文件所在的目录。
2. 然后添加测试工程引用的lib文件名:
项目属性---配置属性---链接器---输入---附加依赖项:加上lib文件名。
(3)添加工程引用的dll动态库,添加到Debug(exe文件的相同目录下)
把引用的dll放到工程的可执行文件所在的目录下。如果不放置在此目录下,会出现如下情况:
测试程序如下:
#include "stdafx.h"#include#include "Win32Dll2.h"//#include "Win32"using namespace std;////extern int addByDll(int a, int b);//extern int subByDll(int a, int b);int _tmain(int argc, _TCHAR* argv[]){ cout << "11 + 8 = " << addByDll(11, 8) << endl; system("pause"); return 0;}
编译通过后,执行:
如果不采用MFC自动提供的方式,如果直接写,则同样有生成Dll和lib文件,但是没有.h文件。
则再CPP文件中直接定义:
_declspec(dllexport) int addByDll(int a, int b){ return a + b;}_declspec(dllexport) int subByDll(int a, int b){ return a - b;}
2. 然后在测试工程中如上述添加lib,以及Dll方式处理。
在需要引用的位置使用如下声明,因为在编译的时候,头文件不参与编译,只编译源文件。 __declspec(dllimport) 则是用来定义从动态链接库中的引用声明。
.h使用文件如下添加从动态链接库的引用声明。
#ifdef WIN32DLL2_EXPORTS #define WIN32DLL2_API __declspec(dllexport) #else #define WIN32DLL2_API __declspec(dllimport) #endif WIN32DLL2_API int addByDll(int a, int b);WIN32DLL2_API int subByDll(int a, int b);
3. DLL可以导出C++类