Windows上使用动/静态库

Windows上使用静态库和动态库

  • 首先理解什么是静态链接库和动态链接库,通过名称我们可以发现,它们两者都是 “xx链接库”,所以他们都是在链接过程中使用的库,我们来回忆一下C++程序的编译过程:
    Windows上使用动/静态库_第1张图片

静态库

之所以称为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。

试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。

静态库特点总结:

  1. 静态库对函数库的链接是放在编译时期完成的。
  2. 程序在运行时与函数库再无瓜葛,移植方便。
  3. 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。

下面介绍一下,如何在VS IDE中编写和使用静态库,

创建静态库

首先编写一个简单的C++类,将其编译成静态库给他人用,头文件MyCalc.h和实现文件MyCalc.cpp如下所示Windows上使用动/静态库_第2张图片
接下设置项目输出文件为静态链接库,并生成库文件:

右键工程=>属性=>配置属性=>常规=>项目默认值=>配置类型 设置为静态库Windows上使用动/静态库_第3张图片
然后我们build项目就可以得到静态库文件

使用静态库:

在VS中使用静态库,这里介绍一下两种情况:

1.在同一个解决方案的子工程中使用静态库,

  • 右键MyClacTest工程=>添加=>引用 勾选MyCalc工程
  • 在MyCalcTest工程中包含MyCalc.h头文件, 右键MyCalcTest工程=>属性=>C/C++=>常规=>附加包含目录(填写MyCalc.h文件所在目录),如下图:
    我们以将MyCalc.h文件拷贝到另外一个目录X,然后附加包含目录填写这个目录X也是可以的
    Windows上使用动/静态库_第4张图片
    做完以上两步,我们就可以在MyCalcTest工程中使用MyCalc.h头文件中的类和方法了,

2.在不同的解决方案中使用静态库(比如使用第三方库)

在我们的工程中使用一些第三方库的时候,就无法添加对MyCalc工程的引用了;我们只能拿到第三方库的头文件(.h)和库文件(.lib);我们可以建一个目录third_party来存放第三方库
Windows上使用动/静态库_第5张图片

  • 右键工程=>属性=>C/C++=>常规=>附加包含目录 (选择third_party/include 目录)
  • 右键工程=>属性=>链接器=>常规=>附加库目录(选择third_parth/lib 目录)
  • 右键工程=>属性=>链接器=>输入=>附加依赖项(填入库的名称, MyCalc.lib)
    做完以上三个配置,就可以在MyClacTest工程中使用第三方库了

动态库

为什么有了静态库,还需要动态库呢?
这其实是因为静态库的缺点所导致的
1. 空间浪费,比如现在有一个静态库A,现在有应用程序B、C,这两个程序都要引用这个静态库,这时候就需要将库A分别链接到B和C中去,如果存在多个程序同时引用库A,那内存中就会有多份库A的拷贝,造成空间浪费
2.热更新问题,比如我们打LOL,某个英雄的技能出现了Bug,造成伤害异常,如果采用静态链接的方式,修复Bug后,那将会对整个程序重新进行编译,打包发布;对于玩家来讲,也许是一个很小的改动,都需要玩家重新下载整个游戏,全量更新

动态库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

动态库特点总结:

  1. 动态库把对一些库函数的链接载入推迟到程序运行的时期。
  2. 可以实现进程之间的资源共享。(因此动态库也称为共享库)
  3. 将一些程序升级变得简单。
  4. 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

使用动态库:

使用动态库一般有两种方式,显式调用和隐式调用
显式调用:只需要一个dll文件,并且知道库中函数的名称,就可以通过系统API, LoadLibrary方法来显示调用库中的某个方法
隐式调用:隐式调用需要三个文件同时使用, 头文件.h,动态库文件.dll,动态库导出库文件.lib,这里的动态库导出库(.lib)文件,里面存放的内容其实就是动态库(.dll)文件中函数的地址信息;动态库在运行时载入,就是通过.lib文件中记录的地址信息,找到.dll文件中的具体函数; (.lib文件一般很小,而.dll文件很大;.lib文件需要在链接时载入到目标代码中,否则会编译不通过(无法解析的外部符号);.dll文件不需要链接到目标代码只需要在运行时放入指定目录就可以实现动态加载)

这里主要介绍一下动态库的隐式调用:

这次将MyCalc项目生成为动态库,并导出其中的MyCalc类:
Windows上使用动/静态库_第6张图片
此时会生成MyCalc.lib和MyCalc.dll这两个文件,这时候就可以配合MyCalc.h头文件来隐式调用动态库了;如果第13行,不对MyCalc类进行导出的话,只会生成MyCalc.dll一个文件,此时只能通过名称来显示调用动态库

动态库的隐式调用配置,与静态库第二种使用方式类似,都是配置 头文件包含目录,库文件目录,附加依赖项(MyCalc.lib),只是在运行时,需要将bin目录中的MyCalc.dll放到exe对应的目录下就行了Windows上使用动/静态库_第7张图片

参考:吴秦大佬的文章

你可能感兴趣的:(windows相关,c++,开发语言)