天天看点

C++ 静态库 与 动态库

目录

  • 基础知识
    • 参考内容
    • 动态库 与 静态库
  • 静态库 创建 与 使用
    • 静态库 的 创建
    • 静态库 的 使用
  • 动态库 创建 与 使用
    • 动态库 的 创建
    • 动态库 的 使用
    • __declspec(dllexport) 与 __declspec(dllimport)

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. 创建空项目
    C++ 静态库 与 动态库
  2. 编写所需要的头文件 和 cpp文件
    C++ 静态库 与 动态库
    C++ 静态库 与 动态库
  3. 可以在该项目 写个main.cpp 测试代码,后期生成库之前的时候注释掉
    C++ 静态库 与 动态库
  4. 打开项目属性 -》 常规 -》配置类型选择静态库 -》确定
    C++ 静态库 与 动态库
  5. 注释main函数,重新生成项目
C++ 静态库 与 动态库
  1. 找到对应的 h文件 和 lib文件 可以将其提取放到 其他地方

在需要用到 该库的项目 设置一些配置 ,可以把 h文件 lib文件放到项目中一些对应位置
  • 方法一:配置项目属性
  1. 添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。
    C++ 静态库 与 动态库
  2. 添加文件引用的lib静态库路径:工程---属性---配置属性---链接器—常规—附加库目录:加上lib文件存放目录。
    C++ 静态库 与 动态库
  3. 然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入—附加依赖项:加上lib文件名。
    C++ 静态库 与 动态库
  4. 使用
    C++ 静态库 与 动态库
  • 方法二:使用编译语句

    #pragma comment(lib,"./mylib.lib")

  • 方法三:添加工程中

    就像 添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.

    切换到"解决方案视图",--->选中要添加lib的工程-->点击右键-->"添加"-->"现有项"-->选择lib文件-->确定.

    C++ 静态库 与 动态库

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

  1. 建立一个空项目
  2. 建立需要的头文件 和 cpp文件
  3. 编写 头文件内容
    C++ 静态库 与 动态库
  4. 编写cpp内容
  5. 在工程属性,C/C++ => 预处理器 => 预处理定义 中添加预定义宏 DLL_EXPORT
    C++ 静态库 与 动态库
  6. 工程属性 -》常规 -》 配置类型 设置 动态库
    C++ 静态库 与 动态库
  7. 生成项目(同理 如果有 main函数,则需要将其注释掉)
    C++ 静态库 与 动态库

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

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

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

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

  1. 将 dll文件拷到 可执行文件的目录下

    否则运行时会出现这个错误:

    C++ 静态库 与 动态库

  • 参考内容:

    __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 中使用的变量。