# 库相关知识点 ## 静态库 ### 静态库的基本概念 静态库(Static Library)是一种预先编译好的程序代码集合,以独立文件形式存在,供其他程序在编译时链接使用。它将多个目标文件(.o 或 .obj)打包为单一文件,简化了程序开发和部署流程。 ### 核心特点 1. **编译时链接** 链接器在编译阶段将静态库中的代码完整复制到可执行文件中,运行时无需依赖外部库文件。 2. **独立性** 生成的可执行文件不依赖外部库,便于在不同环境中部署,但会导致文件体积增大。 3. **格式差异** - **Windows**:通常以 `.lib` 为扩展名 - **Unix/Linux/macOS**:使用 `.a`(archive)扩展名 ### 静态库的生成 使用vs2022选择`C++`的`静态库`创建 ![image-20250709185110253](./pictures/image-20250709185110253.png) 写完代码,点击生成即可生产`.lab`文件 ![image-20250709190120328](./pictures/image-20250709190120328.png) ![image-20250709190224585](./pictures/image-20250709190224585.png) ### 静态库的调用 #### 在工程配置中调用 1. 配置静态库的头文件选择`属性`>`C/C++`>`附加包含目录`将头文件目录配置上去 ![image-20250709191548096](./pictures/image-20250709191548096.png) 2. 配置静态库的所在位置,选择`属性`>`链接器`>`常规`>`附加库目录`配置其所在路径 ![image-20250709191834414](./pictures/image-20250709191834414.png) 3. 配置静态库的所在位置,选择`属性`>`链接器`>`输入`>`附加依赖项`配置其名字 ![image-20250709192153729](./pictures/image-20250709192153729.png) 4. 可以直接使用`#include ` ![image-20250709192522012](./pictures/image-20250709192522012.png) #### 在代码中语句加载lib调用 先把需要引用的头文件还有`.lib`文件放在一起 ```C++ //第一行是引用头文件 //第二行是引用静态库 #include "C:\\Users\\徐加冠\\source\\repos\\LabTest\\x64\\Debug\\StaticLib.h" #pragma comment(lib,"C:\\Users\\徐加冠\\source\\repos\\LabTest\\x64\\Debug\\StaticLib.lib") ``` ![image-20250709191259138](./pictures/image-20250709191259138.png) ## 动态库 ### 动态库的基本概念 动态库(Dynamic Library)是一种在程序运行时才被链接和加载的共享库文件,包含可被多个程序同时使用的代码和数据。与静态库(Static Library)在编译时被完整嵌入到可执行文件中不同,动态库在运行时才被动态加载到内存,实现代码复用并减少内存占用。 ### 核心特点 1. **共享加载**:多个程序可共享同一份动态库实例,减少内存开销。 2. **运行时链接**:程序启动时才加载动态库,而非编译时,提高开发灵活性。 3. **独立更新**:动态库可独立于程序更新,无需重新编译整个程序。 4. 跨平台差异: - Windows:以 `.dll`(Dynamic Link Library)为扩展名。 - Linux/macOS:以 `.so`(Shared Object)或 `.dylib`(Dynamic Library)为扩展名。 ### 动态库的生成 #### 通过导出语句生成 1. 使用vs2022选择动态链接库创建空项目 ![image-20250710102828844](./pictures/image-20250710102828844.png) 2. 分别添加头文件和源文件 头文件的导出语句 ```C++ #pragma once #ifndef BHDLL_d #define BHDLL_d //宏定义导出 #ifdef BHDLL__//如果没有定义DLLH 就定义 DLLH __declspec(dllexport) #define BHDLL __declspec(dllexport)//导出 #else #define BHDLL __declspec(dllimport)//导入 #endif // DLLH__//如果没有定义DLLH 就定义 DLLH //编写代码区域 //导出函数 BHDLL int add(int a, int b); BHDLL int sub(int a, int b); //导出类 class BHDLL dllH { public: int mul(int a, int b); int div(int a, int b); }; //以C语言方式导出函数: extern "C" { BHDLL int Cadd(int a, int b); BHDLL int Csub(int a, int b); } #endif ``` 源文件代码 ```C++ #include "BH_dll.h" #include using namespace std; int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int dllH::mul(int a, int b) { return a * b; } int dllH::div(int a, int b) { return a / b; } int Cadd(int a, int b) { return a + b; } int Csub(int a, int b) { return a - b; } ``` 3. 修改项目属性改为dll动态库 ![image-20250710103417243](./pictures/image-20250710103417243.png) 点击重新生成,即可生成动态链接库 ![image-20250710103520461](./pictures/image-20250710103520461.png) #### 通过模块文件生成 1. 使用vs2022创建一个空项目 ![image-20250710104736756](./pictures/image-20250710104736756.png) 2. 创建一个源文件 ```C++ #include "iostream" void fun1() { std::cout << "fun1" << std::endl; } void fun2() { std::cout << "fun2" << std::endl; } ``` 3. 创建一个edf配置文件 ```edf LIBRARY "test" EXPORTS fun1 fun2 ``` 4. 修改项目的生成为.dll和输出的名字和上面`LIBRARY "test"`定义的名字要一致 ![image-20250710105048084](./pictures/image-20250710105048084.png) 5. 定义模块文件的位置点击`链接器`>`输入`>`模块定义文件` ![image-20250710195629035](./pictures/image-20250710195629035.png) 6. 点击重新生成就可以生成 ![image-20250710105215199](./pictures/image-20250710105215199.png) ### 动态库的调用 #### 在工程配置中调用 1. 点击项目属性配置其`C\C++`>`附加包含目录`,改成需要调用dll所在目录 ![image-20250710123819771](./pictures/image-20250710123819771.png) 2. 点击`链接器`>`常规`>`附加库目录` ![image-20250710124000084](./pictures/image-20250710124000084.png) 3. 点击`链接器`>`输入`>`附加依赖项`输入调用名字 ![image-20250710124140907](./pictures/image-20250710124140907.png) 4. 运行代码时需要把dll放在exe同文件夹下,不然会报错 ![image-20250710124556617](./pictures/image-20250710124556617.png) 5. 放在相同目录下运行成功 ![image-20250710124711322](./pictures/image-20250710124711322.png) #### 在代码中语句加载lib调用 ```C++ #include "D:\\桌面\\x64\\Debug\\DllMy.h" #pragma comment(lib,"D:\\桌面\\x64\\Debug\\DllMy.lib") ``` ![image-20250710125301402](./pictures/image-20250710125301402.png) #### 在代码中语句加载dll调用 ```C++ HINSTANCE Dll = LoadLibrary(L"test.dll"); if (Dll == NULL) { std::cerr << "无法加载DLL! 错误码: " << GetLastError() << std::endl; return 1; } typedef void (*Func)(); // 定义函数指针类型 Func add = (Func)GetProcAddress(Dll, "fun1"); add(); FreeLibrary(Dll); return 0; ``` ![image-20250710130734676](./pictures/image-20250710130734676.png) ps:如果使用导出语句生成的dll,dll内部的函数名称和你定义的不一样,如果使用edf文件导出可以自定义函数名称