C/C++静态库和动态库
C/C++静态库和动态库
目标
- 创建与使用静态库、动态库
- 静态库和动态库的区别
- 使用时如何选择
什么是库?
库是写好的现有的,成熟的,可以复用的代码
库的本质
一种可执行代码的二进制形式,可以被操作系统载入内存执行.
库的种类
- 静态库(
.a
、.lib
) - 动态库(
.so
、.dll
)
程序编译过程:
如图所示:
静态库
本质:
一组目标文件(,.o/.obj,文件的集合).很多目标文件经过压缩打包后形成的一个文件
特点:
- 静态库对函数库的链接是放在编译时期完成的
- 程序在运行时与函数库无瓜葛,移植方便
- 浪费空间和资源,所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件
创建静态库的过程
Windows下创建静态库:
- 使用
vs
命令行生成静态库:
- 使用带编译器选项
/c
的Cl.exe
编译代码(cl/c StaticMath.cpp
),创建名为StaticMath.obj
的目标文件 - 使用库管理器
Lib.exe
链接代码(lib StaticMath.obj
),创建静态链接库StaticMath.lib
- 使用vs工程设置生成静态库:
-
创建
win32
控制台程序时,勾选静态库类型;打开工程“属性面板”è”配置属性”è”常规”,配置类型选择静态库 -
创建的时候选择语言、选择平台、选择库
使用静态库
-
添加
StaticMath.h
头文件目录,打开工程属性面板
->属性配置
->c/c++
->常规
-
在附加包含目录属性值中输入
StaticMath.h
头文件所在目录 -
打开工程
属性面板
->配置属性
->链接器
->命令行
,输入静态库的完整路径
动态库
动态库的存在是为了弥补静态库的不足
静态库的两个缺点:
- 空间浪费
动态库加载示例:
- 静态库对程序的更新、部署和发布页会带来麻烦。静态库
liba.lib
更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)
动态库的特点
- 把对一些库函数的链接载入推迟到程序运行的时期
- 实现进程之间的资源共享(动态库也称之为共享库)
- 程序升级变得简单
- 真正做到链接载入完全由程序员在程序代码中控制->(只显示调用)
动态库加载过程:
Windows
创建动态库:
-
在
Windows
系统下的执行文件格式是PE
格式,动态库需要一个DllMain函数做出初始化的入口,在导出函数的声明时需要有_declspec(dllexport)
关键字。 -
Linux
下gcc
编译的执行文件默认是ELF
格式,不需要初始化入口,亦不需要函数做特别的声明
使用动态库
-
添加
DynamicMath.h
头文件目录,打开工程属性面板
->配置属性
->C/C++
->常规
,在附加包含目录
属性值中,键入DynamicMath.h
头文件所在目录的路径 -
属性面板
->配置属性
->链接器
->常规
,附加依赖库目录中输入,动态库所在目录 -
属性面板
->配置属性
->链接器
->输入
,附加依赖库中输入动态库编译出来的DynamicLibrary.lib
静态库和动态库的Lib
文件
静态库对应的lib文件叫静态库,动态库对应的lib文件叫导入库
静态库:
本身就包含了实际执行代码、符号表等等
动态库:
实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息
动态库的显式调用
Linux下显式调用动态库
#include <dlfcn.h>,提供了下面几个接口:
void * dlopen( const char * pathname, int mode ); // 函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。
void* dlsym(void* handle,const char* symbol); // dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
int dlclose (void *handle);// dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
const char *dlerror(void);// 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
Windows下显式调用动态库
应用程序必须进行函数调用以在运行时显式加载DLL
显式链接到DLL
,应用程序必须:
- 调用
LoadLibrary
(或相似函数),以加载Dll
和获取模块句柄 - 调用
GetProcAddress
,以获取指向Application
要调用的每个导出函数的函数指针,应用程序是通过指针调用DLL
的函数,编译器不生成外部引用,故无需与导入库链接 - 使用完
Dll
以后调用FreeLibrary
总结
静态库和动态库的区别:
代码被载入的时刻不同--->生成的文件后缀也不同(静态库.a
,lib
)、(动态库.so
,dll
)
- 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大
- 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)