C++ 静态库 与 动态库

基础知识

参考内容

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实现的

静态库 的 创建

  1. 创建空项目

  2. 编写所需要的头文件 和 cpp文件

  3. 可以在该项目 写个main.cpp 测试代码,后期生成库之前的时候注释掉

  4. 打开项目属性 -》 常规 -》配置类型选择静态库 -》确定

  5. 注释main函数,重新生成项目

  1. 找到对应的 h文件 和 lib文件 可以将其提取放到 其他地方

静态库 的 使用

在需要用到 该库的项目 设置一些配置 ,可以把 h文件 lib文件放到项目中一些对应位置

  • 方法一:配置项目属性
  1. 添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。

  2. 添加文件引用的lib静态库路径:工程---属性---配置属性---链接器—常规—附加库目录:加上lib文件存放目录。

  3. 然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入—附加依赖项:加上lib文件名。

  4. 使用

  • 方法二:使用编译语句
    #pragma comment(lib,"./mylib.lib")
  • 方法三:添加工程中
    就像 添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.
    切换到"解决方案视图",--->选中要添加lib的工程-->点击右键-->"添加"-->"现有项"-->选择lib文件-->确定.

动态库 创建 与 使用

创建 和 配置信息 和静态库类似

动态库 的 创建

  1. 建立一个空项目

  2. 建立需要的头文件 和 cpp文件

  3. 编写 头文件内容

  4. 编写cpp内容

  5. 在工程属性,C/C++ => 预处理器 => 预处理定义 中添加预定义宏 DLL_EXPORT

  6. 工程属性 -》常规 -》 配置类型 设置 动态库

  7. 生成项目(同理 如果有 main函数,则需要将其注释掉)

动态库 的 使用

  1. 配置项目属性 (和静态库一致)

A、添加工程的头文件目录:工程---属性---配置属性---c/c++---常规—附加包含目录:加上头文件存放目录。

B、添加文件引用的lib静态库路径:工程---属性---配置属性—链接器—常规—附加库目录:加上lib文件存放目录。

C 然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入—附加依赖项:加上lib文件名。

  1. 将 dll文件拷到 可执行文件的目录下
    否则运行时会出现这个错误:

__declspec(dllexport) 与 __declspec(dllimport)

声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类

  • __declspec(dllimport)

声明一个导入函数,是说这个函数是从别的DLL导入。一般用于使用某个dll的exe中 不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量

posted @ 2021-04-09 15:53  Linese  阅读(704)  评论(0编辑  收藏  举报