5.03 动态库

动态库特点

● 动态库特点

  1. 运行时独立存在(独立内存空间)

  2. 源码不会链接到执行程序(不会抓源码 只存地址)

  3. 使用时加载(使用动态库必须使动态库执行)

● 与静态库的比较

  1. 由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码.所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小

  2. 静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或地址)未变化,其他使用 DLL 的程序不需重新链接

● 内容

dll 文件包含 函数文件头(函数名,函数标号与地址)和函数源码

配套的 lib 包含 函数名,函数标号以及 dll 文件名

动态库创建

● 创建动态库项目

● 添加库程序

● 库程序导出-提供给使用者库中的函数等信息.

1)声明导出:使用_declspec(dlexport) 导出函数(此时是换名函数)

  1. _declspec(dlexport) int add(){
  2. ...
  3. };

注意:动态库编译链接后,也会有 LIB 文件,是作为动态库函数映射使用

  1. 模块定义文件.def(函数不会换名)

例如: LIBRARY DLLFunc //库名称 EXPORTS //库导出表 DLL_Mul @1 //导出的函数

  1. // CppDll.def
  2. LIBRARY CPPdll
  3. EXPORTS
  4. CPP_add @1
  5. CPP_sub @2

动态库的使用

● 隐式链接(操作系统负责使动态库执行) 1)头文件和函数原型

可以在函数原型的声明前,

  1. 增加_declspec(dllimport)
  2. 导入动态库的 LIB 文件
  3. 在程序中使用函数
  4. 隐式链接的情况,dll 文件可以存放的路径
    • (1)与执行文件中同一个目录下
    • (2)当前工作目录
    • (3)Windows 目录
    • (4)Windows/System32 目录
    • (5)Windows/System
    • (6)环境变量 PATH 指定目录
  1. _declspec(dllimport) int add(int a,int b);
  2. #pragma comment(lib,"CPPdll.lib"); // 抓取附属静态库
  3. add()...// 正常使用

● 显式链接(程序员自己负责使动态库执行

1)定义函数指针类型 typedef

2)加载动态库

  1. HMODULE LoadLibrary(
  2. LPCTSTR IpFileName //动态库文件名或全路径
  3. ); 返回 DLL 的实例句柄( HINSTANCE)

3)获取函数地址

  1. FARPROC GetProcAddress(
  2. HMODULE hModule//DLL 句柄
  3. LPCSTR IpProcName //函数名称
  4. );成功返回函数地址

4)使用函数

5)卸载动态库

  1. BOOL FreeLibrary(
  2. HMODULE hModule //DLL 的实例句柄
  3. );
  1. typedef int(*ADD)(int m,int n);
  2. HINSTANCE/HMODULE hDll = LoadLibrary(CppDll.dll);
  3. ADD myADD = (ADD)GetProcAddress(hDll,"CPPADD");
  4. myADD()...
  5. FreeLibrary(hDll);

动态库中封装类

导出的不是类地址, 而是类的成员函数地址

在类名称前增加_declspec(dllexport) 定义,例如

  1. class _declspec(dllexport) CMath {
  2. ...
  3. }

通常使用预编译开关切换类的导入导出定义,例如

  1. // 为了制作者,使用者共有一个头文件, 需要判断,整个宏
  2. #ifndef _DLLCLASS_H
  3. #define _DLLCLASS_H
  4. #ifdef DLLCLASS_EXPORTS
  5. #define EXT_CLASS _declspec(dllexport)//DLL
  6. #else
  7. #define EXT_CLASS _declspec(dllimport)//使用者
  8. #endif
  9. class EXT_CLASS CMath(
  10. ...
  11. }
  12. // 源码.cpp
  13. #define DLLCLASS_EXPORTS // 这样制作动态库 就按导出算
  14. ...