基础知识
参考内容
C++静态库与动态库的区别
通俗理解动态库与静态库区别
静态库与动态库的优缺点
动态库和静态库的理解
《程序员的自我修养——链接、装载与库》
lib 和 dll 的区别、生成以及使用详解
C++创建和使用动态链接库
C++动态库封装及调用
动态库 与 静态库
静态库 在 unix系统中 是 .a 文件,在window系统是 .lib文件
动态库 在 unix系统中 是 .so文件,在window系统是 .dll文件
最本质的区别:该库是否被编译进目标程序内部
他们之间的区别在于 程序编译的阶段,操作上不同。
- 程序编译步骤:预编译 -> 编译 -> 汇编 -> 链接
- 静态库和动态库就是在链接阶段行为不同
静态库在链接阶段将会变生成的目标文件.o 和 引用到的库一起链接打包到可执行文件中。
动态库只有在程序运行时 需要使用到库的时候,才加载库代码。
静态库 | 动态库 | |
---|---|---|
特点 | 静态库对函数库的链接是放在编译时期完成的 | 动态库把对一些库函数的链接载入推迟到程序运行的时期 |
优点 | 1.程序在运行时与函数库再无瓜葛,移植方便 2.编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容 3.代码装载速度快,执行速度略比动态链接库快 4.只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题 |
1.将一些程序升级变得简单 2.更加节省内存并减少页面交换 3.可以实现进程之间的资源共享,共用库 4.产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件 5.DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性 6.不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数 |
缺点 | 1.空间浪费,使用静态库的进程相当于复制一份静态库代码到程序中中,如果多个进程都使用,就会多复制几份 2.更新问题:如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新) |
1.使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在 2.如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息 3.速度比静态链接慢 |
应用场景 | 从函数库集成的角度,若要将发布的所有子库(不止一个)集成为一个动态库向外提供接口,那么就需要将所有子库编译为静态库,这样所有子库就可以全部编译进目标动态库中,由最终的一个集成库向外提供功能。 | 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试 从产品化的角度,发布的算法库或功能库尽量使动态库,这样方便更新和升级,不必重新编译整个可执行文件,只需新版本动态库替换掉旧动态库即可 |
静态库 创建 与 使用
静态库 和 动态库的 创建使用 都是基于 window平台 ,VS实现的
静态库 的 创建
-
创建空项目
-
编写所需要的头文件 和 cpp文件
-
可以在该项目 写个main.cpp 测试代码,后期生成库之前的时候注释掉
-
打开项目属性 -》 常规 -》配置类型选择静态库 -》确定
-
注释main函数,重新生成项目
- 找到对应的 h文件 和 lib文件 可以将其提取放到 其他地方
静态库 的 使用
在需要用到 该库的项目 设置一些配置 ,可以把 h文件 lib文件放到项目中一些对应位置
- 方法一:配置项目属性
-
添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。
-
添加文件引用的lib静态库路径:工程---属性---配置属性---链接器—常规—附加库目录:加上lib文件存放目录。
-
然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入—附加依赖项:加上lib文件名。
-
使用
- 方法二:使用编译语句
#pragma comment(lib,"./mylib.lib")
- 方法三:添加工程中
就像 添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.
切换到"解决方案视图",--->选中要添加lib的工程-->点击右键-->"添加"-->"现有项"-->选择lib文件-->确定.
动态库 创建 与 使用
创建 和 配置信息 和静态库类似
动态库 的 创建
-
建立一个空项目
-
建立需要的头文件 和 cpp文件
-
编写 头文件内容
-
编写cpp内容
-
在工程属性,C/C++ => 预处理器 => 预处理定义 中添加预定义宏 DLL_EXPORT
-
工程属性 -》常规 -》 配置类型 设置 动态库
-
生成项目(同理 如果有 main函数,则需要将其注释掉)
动态库 的 使用
- 配置项目属性 (和静态库一致)
A、添加工程的头文件目录:工程---属性---配置属性---c/c++---常规—附加包含目录:加上头文件存放目录。
B、添加文件引用的lib静态库路径:工程---属性---配置属性—链接器—常规—附加库目录:加上lib文件存放目录。
C 然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入—附加依赖项:加上lib文件名。
- 将 dll文件拷到 可执行文件的目录下
否则运行时会出现这个错误:
__declspec(dllexport) 与 __declspec(dllimport)
-
参考内容:
__declspec(dllimport)的作用到底在哪里呢
关于C++的dllexport和dllimport -
_declspec(dllexport)
声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类
- __declspec(dllimport)
声明一个导入函数,是说这个函数是从别的DLL导入。一般用于使用某个dll的exe中 不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。