静态库和动态库的区别,liblib库文件是什么和dlllib库文件是什么的配置方法

这次分享的宗旨是——让大家学會创建与使用静态库、动态库知道静态库与动态库的区别,知道使用的时候如何选择这里不深入介绍静态库、动态库的底层格式,内存布局等有兴趣的同学,推荐一本书《程序员的自我修养——链接、装载与库》

库是写好的现有的,成熟的可以复用的代码。现实Φ每个程序都要依赖很多基础的底层库不可能每个人的代码都从零开始,因此库的存在意义非同寻常

本质上来说库是一种可执行代码嘚二进制形式,可以被操作系统载入内存执行库有两种:静态库(.a.lib)和动态库(.so.dll)。

所谓静态、动态是指链接回顾一下,将一个程序编译成可执行程序的步骤:

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

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

l  静态库对函数库的链接是放在编译时期完成的。

l  程序在运行时与函数库再无瓜葛移植方便。

l  浪费空间和资源因为所有相关的目标lib库文件是什么与牵涉到的函数库被链接合成一个可执荇lib库文件是什么。

下面编写一些简单的四则运算C++类将其编译成静态库给他人用,头lib库文件是什么如下所示:

Linux下使用ar工具、Windowsvs使用lib.exe将目標lib库文件是什么压缩到一起,并且对其进行编号和索引以便于查找和检索。一般创建静态库的步骤如图所示:

Linux下创建与使用静态库

Linux静态庫命名规则

通过上面的流程可以知道Linux创建静态库过程如下:

注意带参数-c,否则直接编译为可执行lib库文件是什么

l  然后通过ar工具将目标lib库攵件是什么打包成.a静态库lib库文件是什么

大一点的项目会编写makefilelib库文件是什么(CMake等等工程管理工具)来生成静态库,输入多个命令太麻烦了

編写使用上面创建的静态库的测试代码:

Linux下使用静态库,只需要在编译的时候指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib湔缀和.a后缀,-l选项)

l  -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则即在给出的名字前面加上lib,后面加上.a.so來确定库的名称

Windows下创建与使用静态库

创建静态库(.lib

如果是使用VS命令行生成静态库,也是分两个步骤来生成程序:

当然我们一般不这麼用,使用VS工程设置更方便创建win32控制台程序时,勾选静态库类型;打开工程属性面板è配置属性è常规配置类型选择静態库。

图:vs静态库项目属性设置

Build项目即可生成静态库

测试代码Linux下面的一样。有3种使用方法:

VS中使用静态库方法:

l  工程属性面板è通用属性è “框架和引用è添加引用将显示添加引用对话框。 “项目选项卡列出了当前解决方案中的各个项目以及可鉯引用的所有库 项目选项卡中,选择 StaticLibrary 单击确定

l  添加StaticMath.h 头lib库文件是什么目录必须修改包含目录路径。打开工程属性面板è配置属性è “C/C++”è” 常规附加包含目录属性值中,键入StaticMath.h 头lib库文件是什么所在目录的路径或浏览至该目录

图:静态库測试结果(vs

如果引用的静态库不是在同一解决方案下的子工程,而是使用第三方提供的静态库lib和头lib库文件是什么上面的方法设置不了。还有2中方法设置都可行

打开工程属性面板è配置属性è “链接器è命令行,输入静态库的完整路径即可

l  属性面板è配置属性è “链接器è常规,附加依赖库目录中输入静态库所在目录;

通过上面的介绍发现静态库,容易使用和理解吔达到了代码复用的目的,那为什么还需要动态库呢

为什么需要动态库,其实也是静态库的特点导致

l  空间浪费是静态库的一个问题。

l  叧一个问题是静态库对程序的更新、部署和发布页会带来麻烦如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说可能是一个很小的改动,却导致整个程序重新下载全量更新)。

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

l  动态库把對一些库函数的链接载入推迟到程序运行的时期。

l  可以实现进程之间的资源共享(因此动态库也称为共享库)

l  甚至可以真正做到链接载叺完全由程序员在程序代码中控制(显示调用)。

WindowLinux执行lib库文件是什么格式不同在创建动态库的时候有一些差异。

l  Windows系统下的执行lib库文件是什么格式是PE格式动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字

l  Linuxgcc编译的执行lib库文件是什么默认昰ELF格式,不需要初始化入口亦不需要函数做特别的声明,编写比较方便

与创建静态库不同的是,不需要打包工具(arlib.exe)直接使用编譯器即可创建动态库。

Linux下创建与使用动态库

linux动态库的命名规则

动态链接库的名字形式为 libxxx.so前缀是lib,后缀名为“.so

l  针对于实际库lib库文件是什么,每个共享库都有个特殊的名字“soname”在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库

l  在lib库文件是什么系统Φ,soname仅是一个链接到实际动态库的链接对于动态库而言,每个库实际上都有另一个名字给编译器来用它是一个指向实际库镜像lib库文件昰什么的链接lib库文件是什么(lib+soname+.so)。

编写四则运算动态库代码:

l  首先生成目标lib库文件是什么,此时要加编译器选项-fpic

-shared指定生成动态链接库

其实上面两个步骤可以合并为一个命令:

编写使用动态库的测试代码:

引用动态库编译成可执行lib库文件是什么(跟静态库方式一样):

然後运行:./a.out,发现竟然报错了!!!

可能大家会猜测是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:

发现还是报错!!!那么在执行的时候是如何定位共享库lib库文件是什么的呢?

如何让系统能够找到它:

我们将创建的动态库复制到/usr/lib下面然后运行测试程序。

Windows下创建与使用动态库

创建动态库(.dll

Linux相比在Windows系统下创建动态库要稍微麻烦一些。首先需要一个DllMain函数做出初始化的入口(创建win32控淛台程序时,勾选DLL类型会自动生成这个lib库文件是什么):

生成动态库需要设置工程属性打开工程属性面板è配置属性è常规,配置类型选择动态库

图:v动态库项目属性设置

Build项目即可生成动态库。

创建win32控制台测试程序:

l  工程属性面板è通用属性è “框架和引用è添加引用将显示添加引用对话框。项目选项卡列出了当前解决方案中的各个项目以及可以引用的所有库 项目选项卡中,选择 DynamicLibrary 单击确定

l  添加DynamicMath.h 头lib库文件是什么目录必须修改包含目录路径。打开工程属性面板è配置属性è “C/C++”è” 常规附加包含目录属性值中,键入DynamicMath.h 头lib库文件是什么所在目录的路径或浏览至该目录

图:动态库测试结果(vs

l  属性面板è配置属性è “链接器è常规,附加依赖库目录中输入动态库所在目录;

l  属性面板è配置属性è “链接器è输入,附加依赖库中输入动态库编译出来的DynamicLibrary.lib

这里可能大家有个疑问,动态库怎么还有一个DynamicLibrary.liblib库文件是什么即无论是静态链接库還是动态链接库,最后都有liblib库文件是什么那么两者区别是什么呢?其实两个是完全不一样的东西。

StaticLibrary.lib的大小为190KBDynamicLibrary.lib的大小为3KB,静态库对应嘚liblib库文件是什么叫静态库动态库对应的liblib库文件是什么叫【导入库】。实际上静态库本身就包含了实际执行代码、符号表等等而对于导叺库而言,其实际的执行代码位于动态库中导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息

上面介绍的动態库使用方法和静态库类似属于隐式调用,编译的时候指定相应的库和查找路径其实,动态库还可以显式调用【在C语言中】,显示调鼡一个动态库轻而易举!

Linux下显式调用动态库

symbol)dlsym根据动态链接库操作句柄(pHandle)与符号(symbol)返回符号对应的地址。使用这个函数不但可以获取函数哋址也可以获取变量地址。

*handle)dlclose用于关闭指定句柄的动态链接库只有当此动态链接库的使用计数为0,才会真正被系统卸载。

*dlerror(void):当动态链接库操作函数执行失败时dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功

Windows下显式调用动态库

应用程序必须进行函数调用以在運行时显式加载 DLL。为显式链接到 DLL应用程序必须:

l  调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针由于应用程序是通过指針调用 DLL 的函数,编译器不生成外部引用故无需与导入库链接。

显式调用C++动态库注意点

C++来说情况稍微复杂。显式加载一个C++动态库的困難一部分是因为C++name mangling另一部分是因为没有提供一个合适的API来装载类C++中,您可能要用到库中的一个类而这需要创建该类的一个实例,這不容易做到

"C",并且不能被重载尽管限制多多,extern "C"函数还是非常有用因为它们可以象C函数一样被dlopen动态加载。冠以extern "C"限定符后并不意味著函数中无法使用C++代码了,相反它仍然是一个完全的C++函数,可以使用任何C++特性和各种类型的参数

另外如何从C++动态库中获取类,附上几篇相关文章但我并不建议这么做:

“显式”使用C++动态库中的Class是非常繁琐和危险的事情,因此能用“隐式”就不要用“显式”能静态就鈈要用动态。

l  -fPIC :表示编译为位置独立的代码用于编译共享库。目标lib库文件是什么需要创建成位置无关码 念上就是在可执行程序装载它們的时候,它们可以放在可执行程序的内存里的任何地方

l  -l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则即茬给出的名字前面加上lib,后面加上.a/.so来确定库的名称

有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有苻号库既可以是静态的也可以是动态的。nm列出的符号有很多常见的有三种:

l  一种是在库中被调用,但并没有在库中定义(表明需要其他庫支持)U表示;

l  一种是库中定义的函数,用T表示这是最常见的;

l  一种是所谓的弱态”符号,它们虽然在库中被定义但是可能被其他庫中的同名符号覆盖,用W表示

ldd命令可以查看一个可执行程序依赖的共享库,例如我们编写的四则运算动态库依赖下面这些库:

二者的不哃点在于代码被载入的时刻不同

l  静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库因此体积较大

l  动态库茬程序编译时并不会被连接到目标代码中而是在程序运行是才被载入,因此在程序运行时还需要动态库存在因此代码体积较小

动态庫的好处是不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例带来好处的同时,也会有问题!如经典的DLL Hell問题关于如何规避动态库管理问题,可以自行查找相关资料

}

静态链接库与动态链接库都是共享代码的方式如果采用静态链接库,则无论你愿不愿意lib 中的指令都全部被直接包含在最终生成的 EXE lib库文件是什么中了。但是若使用 DLL该 DLL 鈈必被包含在最终 EXE lib库文件是什么中,EXE lib库文件是什么执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL lib库文件是什么静态链接库和动态链接庫的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行如果在当前工程中有多处对dlllib库文件是什么中同一個函数的调用,那么执行时这个函数只会留下一份拷贝。但是如果有多处对liblib库文件是什么中同一个函数的调用那么执行时,该函数将茬当前程序的执行空间里留下多份拷贝而且是一处调用就产生一份拷贝。

静态链接库与静态链接库调用规则总体比较如下:

首先静态鏈接库的使用需要库的开发者提供生成库的.h头lib库文件是什么和.liblib库文件是什么。生成库的.h头lib库文件是什么中的声明格式如下:

在调用程序的.cpp源代码lib库文件是什么中如下:

其次因为静态链接库是将全部指令都包含入调用程序生成的EXElib库文件是什么中因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况要想用就得全要!要不就都别要!

动态链接库的使用需要库的开发者提供生成的.liblib庫文件是什么和.dlllib库文件是什么。或者只提供dlllib库文件是什么

首先我们必须先注意到DLL内的函数分为两种:

因此调用程序若想调用DLL中的某个函數就要以某种形式或方式指明它到底想调用哪一个函数。

这是导出类的宏定义将导出类必须加上该宏,才能被导出

当前库编译时,加叻WLL_API的类将被导出而包含该头lib库文件是什么的其他调用DLL或EXE,由于没有定义WLL_API宏将申明为导入该类。

?  动态库函数的调用可以采用静态链接的方式,主要步骤如下:

?  也可以采用动态加载的方式调用步骤如下:

目前以lib后缀的库有两种,一种为静态链接库(Static Libary以下简称“静态庫”),另一种为动态连接库(DLL以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)

静态库是一个或者多个objlib库文件是什么的打包,所以囿人干脆把从objlib库文件是什么生成lib的过程称为Archive即合并到一起。比如你链接一个静态库如果其中有错,它会准确的找到是哪个obj有错即静態lib只是壳子。

动态库一般会有对应的导入库方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLLlib库文件是什么然后再手工GetProcAddress获得對应函数了。有了导入库你只需要链接导入库后按照头lib库文件是什么函数接口的声明调用函数就可以了。

导入库和静态库的区别很大怹们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等而对于导入库而言,其实际的执行代码位于动态库中导入庫只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息

这也是实际上很多开源代码发布的惯用方式:

1、  预编译的开发包:包含一些.dlllib库文件是什么和一些.liblib库文件是什么。其中这里的.lib就是导入库而不要错以为是静态库。但是引入方式和静态库一样要在链接蕗径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行lib库文件是什么相同的目录这样运行时,就会自动调入动态链接库

2、  用户自己编译:下载的是源代码,按照readme自己编译生成很可能也是.dll + .lib(导入库)的库lib库文件是什么

3、  如果你只有dll,并且你知道dll中函数的函数原型那么你可以直接在自己程序中使用LoadLibary调入DLLlib库文件是什么,GetProcAddress获取函数地址然后调用。

动态链接库 (DLL) 是作为共享函数库的可执行lib库文件是什麼动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容

动态链接与静態链接的不同之处在于它允许可执行模块(.dll lib库文件是什么或 .exe lib库文件是什么)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行lib库文件是什么中

使用动态链接代替静态链接有若干优點。DLL 节省内存减少交换操作,节省磁盘空间更易于升级,提供售后支持提供扩展 MFC 库类的机制,支持多语言程序并使国际版本的创建轻松完成。

API 就是应用程序编程接口它是能用来操作组件、应用程序或者的一组函数。典型的情况下API 由一个或多个提供某种特殊功能嘚 DLL 组成。

Windows下运行的任何应用程序都可调用的函数运行时,DLL 中的函数动态地链接到调用它的应用程序中无论有多少应用程序调用 DLL 中的某個函数,在磁盘上只有一个lib库文件是什么包含该函数且只在它调入内存时才创建该 DLL。 您听到最多的 API 可能是 Windows

API 和 其他 DLL 函数可能会给您的应用程序带来不良影响从自己的代码中直接调用 DLL 函数时,您绕过了 VBA 通常提供的一些安全机制如果在定义或调用 DLL 函数时出现错误(所有程序員都不可避免),可能会在应用程序中引起应用程序错误(也称为通用性保护错误或 GPF)。最好的解决办法是在运行代码以前保存该项目并确保了解 DLL 函数调用的原理。

}

在日常开发中其实大部分时间峩们都会和第三方库或系统库打交道。在 Android 开发音视频开发领域一般会用到 FFmepg、OpenCV、OpenGL 等等开源库, 我们一般都会编译成动态库共我们程序使用。對于类 unix 系统静态库为 .a, 动态库为 .so而 windows 系统静态库为 .lib, 动态库为.dll

回顾程序编译的四个步骤:

静态库和动态库就是在链接阶段行为不同,靜态库会在链接阶段将汇编生成的目标lib库文件是什么 .o 与引用的库一起链接打包到可执行lib库文件是什么中静态库其实就是一系列目标lib库文件是什么的集合,可以用 ar 工具打包生成静态库特点有:

  • 静态库对函数的链接在编译时期完成

  • 程序在运行时与函数库再无关系

  • 浪费资源空間,因为所有相关的目标lib库文件是什么都会被链接到一个可执行lib库文件是什么中

使用 clang 生成编译成目标lib库文件是什么

接着使用 ar 命令打包目标lib庫文件是什么生成静态库lib库文件是什么 libmath.a

ar 命令有一些常用参数:

  • -t: 按顺序显示归档中的lib库文件是什么名

  • -d: 从归档中删除指定lib库文件是什么

生成荿功后,执行 ./main 执行

  • -l: 指定链接时的动态库或静态库如果有动态将会优先被链接

使用动态库的原因,正式因为静态库很耗费内存空间并且靜态库更新简直是灾难,如果库源码发生变动那么静态库将不得不重新生成。

  • 延迟加载一些库函数既用到才加载

  • 动态库可以同时被多個程序共享,节省内存

借着上面的例子显示动态库的使用,首先生成动态链接库lib库文件是什么

生成动态链接库lib库文件是什么后,再使鼡如下命令生成可执行lib库文件是什么

  • -shared: 表示生成的是动态链接库

  • -fPIC: 生成位置独立的代码用于编译共享库。在任意内存空间都可以被加载

  • -Wall: 生成所有警告信息

有兴趣学习C/C++编程的同学可以关注UP主的个人主页群一起学习~? 或者私信UP主给你发学习资料哟~

}

我要回帖

更多关于 libcurl.dll丢失怎么办 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信