库的概念

库:实现了某一类功能的若干函数和二进制代码的集合。库的后缀名在不同平台上表现不同:
Windows:静态库:xxx.lib && 动态库:xxx.dll
Linux:静态库:xxx.a && 动态库:xxx.so

库分为静态库和动态库,与之对应的操作是静态链接和动态链接,静态库不能采用动态链接,同理,动态库也不能采用静态链接。

静态库:在链接的时候,函数库被完整的拷贝到可执行文件中,对应的链接方式成为静态链接,采用gcc -static指令。这里的可执行文件可以使单纯的一个a.out,也可以是一整个app或者程序。

动态库:相对于静态库,动态库并没有将库中所有的数据复制到可执行文件中,在程序运行的时候才会被动态载入。

备注
动态链接可以理解成只是将声明文件复制到了程序中。在运行时根据预先设置的动态库的位置和这部分声明来调用对应的库。所以说动态库也叫共享库,共享在整个系统中。对于iOS系统而言,所有系统提供的.framework都是动态库且在各个app之间共享。但是iOS基于沙盒模式,其不允许用户自己创建动态的.framework。即使在iOS8之后可以创建动态framework,但其本质还是将动态库放入了app的沙盒中。iOS不允许包含自定义动态库的app上架到app store,所以iOS中的动态库只能应用在不上架app store的企业应用中。

静态库和动态库的区别和特点

静态库:
1、一旦链接完成,执行程序就和函数库没有任何关联
2、占用空间和资源,拷贝多次就会占用多份资源
3、会导致升级不便,一个地方修改就需要全量更新

动态库:
1、可以实现进程之间的资源共享
2、动态库把对一些库函数的链接载入推迟到程序运行的时期
3、将一些程序升级变得简单
4、可以通过显示调用做到链接载入完全由程序员在程序代码中控制
5、动态库的创建直接使用编译器即可创建动态库,不需要打包工具(ar、lib.exe

示例代码

文件夹结构:

mymath.h文件:

// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int xkadd(int a, int b);
int xksum(int a, int b);
#endif

mymath.c文件:

// mymath.c
int xkadd(int a, int b){return a+b;
}
int xksum(int a, int b){return a-b;
}

test.c文件:

// test.c
#include <stdio.h>
#include "mymath.h"// 自定义头文件
int main(){int a = 2;int b = 3;int sum = xkadd(a, b);printf("a=%d, b=%d, a+b=%d\n", a, b, sum);
}

静态库的生成和使用

// 进入函数库所在文件夹
caoxkdembp:static-lib caoxk$ cd /Users/caoxk/Demo/static-lib/lib
// 将函数库编译成.o文件
caoxkdembp:lib caoxk$ gcc -c mymath.c
// 将.o文件使用ar工具生成.a静态库
caoxkdembp:lib caoxk$ ar -crv libmymath.a mymath.o
// 这一行是上一行命令执行结果的输出
a - mymath.o
caoxkdembp:lib caoxk$ cd ..
caoxkdembp:static-lib caoxk$ gcc test.c -L ./lib/ -lmymath
// 未告知编译器对应的头文件地址,执行命令后报错
test.c:4:10: fatal error: 'mymath.h' file not found
#include "mymath.h"// 自定义头文件^~~~~~~~~~
1 error generated.
// 使用-I执行告诉编译器libmymath.a对应的头文件所在的地址
caoxkdembp:static-lib caoxk$ gcc test.c -L ./lib/ -lmymath -I ./lib/
// 执行可执行文件
caoxkdembp:static-lib caoxk$ ./a.out
a=2, b=3, a+b=5

最终的文件夹结构:

Static-Lib End

总结
静态库的使用需要结合头文件,比如上面直接gcc主文件和mymath库时,没有使用-I path告知头文件的地址,所以会找不到头文件。而iOS中的framework其实包含三种文件:.h头文件、.a静态库、资源文件,如图片等

动态库/共享库的生成

caoxkdeMacBook-Pro:lib caoxk$ cd /Users/caoxk/Demo/dynamic-lib
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ls
lib test.c
caoxkdeMacBook-Pro:dynamic-lib caoxk$ cd lib/
// 生成费共享的目标文件.o
caoxkdeMacBook-Pro:lib caoxk$ gcc -c -fpic mymath.c
// 使用gcc -shared的第二层意义来生成动态链接库
caoxkdeMacBook-Pro:lib caoxk$ gcc -shared -o libmymath.so mymath.o
caoxkdeMacBook-Pro:lib caoxk$ cd ..
caoxkdeMacBook-Pro:dynamic-lib caoxk$ pwd
/Users/caoxk/Demo/dynamic-lib
// -I:在./lib中寻找头文件;-L:在./lib中寻找;lmymath:连接libmymath.so动态库
caoxkdeMacBook-Pro:dynamic-lib caoxk$ gcc test.c -I ./lib/ -L ./lib/ -lmymath
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ./a.out
dyld: Library not loaded: libmymath.soReferenced from: /Users/caoxk/Demo/dynamic-lib/./a.outReason: image not found
Abort trap: 6
caoxkdeMacBook-Pro:dynamic-lib caoxk$

以上执行后,找不到动态库。因为mac中不能使用ldd指令,所以使用otool -L指令来查询执行文件中动态库的路径,如下:

caoxkdeMacBook-Pro:dynamic-lib caoxk$ ldd a.out
-bash: ldd: command not found
caoxkdeMacBook-Pro:dynamic-lib caoxk$ otool -L a.out
a.out:libmymath.so (compatibility version 0.0.0, current version 0.0.0)/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
caoxkdeMacBook-Pro:dynamic-lib caoxk$

以上结果表明:存在两个库,一个是文件路径为/usr/lib/libSystem.B.dylib的库,另一个是没有路径的libmymath.so库,也就是我们自定义的动态库没有设置路径,或者说是和a.out同级,将libmymath.so复制到a.out同级目录后运行:

caoxkdeMacBook-Pro:dynamic-lib caoxk$ cp lib/libmymath.so ./
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ./a.out
a=2, b=3, a+b=5
caoxkdeMacBook-Pro:dynamic-lib caoxk$

那么这个问题如何解决呢?首先我们知道动态库的寻址顺序是:
1、编译目标代码时指定的动态库搜索路径
2、环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3、配置文件/etc/ld.so.conf中指定的动态库搜索路径
4、默认的动态库搜索路径/lib
5、默认的动态库搜索路径/usr/lib

也就是说我们需要告诉ld我们自定义的动态库的地址。这里引入一个指令:-Wl,-rpath=xxx(mac 中需要使用-Wl,rpath xxx或者-Wl,rpath,dir1,dir2,dir3)。这个指令的意思是指定runtime时的动态库寻址地址。而-L xxx是指定链接时库的寻址地址。

网上有几种方法:
1、将自动以的动态库复制到到/usr/lib中(权限不允许)
2、使用export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:《your_lib_path》设置临时增加链接动态库的路径(无效)
3、通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变(未测试)
4、使用-Wl -rpath(无效)

所以这种情况如何解决?-WL -rpath的正确用法是什么?问题暂时留存

动态库和静态库相关的指令

-fpic:生成非共享模式的目标文件
-static:一般来讲,很多函数库会有静态库和动态库两个版本。这个-static是编译阶段的链接选项,只在链接时不链接动态库,全部链接静态库,所以生成的可执行文件会比较大。
-shared:这个指令有两个意思。不作为链接选项时,是告诉gcc生成一个动态库,使用格式是gcc -shared xxx.o -o libxxx.so 。作为编译选项时,和-static对立,尽量使用动态库,只有在没有动态库时才链接静态库。是默认选项
比如:

// 生成非共享模式的机器码文件
caoxkdembp:lib caoxk$ gcc -fpic -c mymath.c
// 生成动态库
caoxkdembp:lib caoxk$ gcc -o libmymath.so mymath.o
Undefined symbols for architecture x86_64:"_main", referenced from:implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这里报错的原因是不加-shared,gcc默认执行的指令时编译并链接最终生成可执行文件,而mymath.c是一个函数库,当然没有main函数。没用main函数当然不能生成可执行文件

更多文章

C语言底层原理(二):动态库、静态库相关推荐

  1. c语言makecode头文件,cmake 添加头文件目录,链接动态、静态库

    罗列一下cmake常用的命令. CMake支持大写.小写.混合大小写的命令. 1. 添加头文件目录INCLUDE_DIRECTORIES 语法: include_directories([AFTER| ...

  2. CMake教程(二)- 添加静态库文件和动态库文件

    CMake教程(二)- 添加静态库文件和动态库文件 什么是库文件 静态链接库 动态链接库 静态库和动态库的区别 如何在CMake中添加库文件 CMake 中 target_link_libraries ...

  3. 『Go 语言底层原理剖析』文末送书

    互联网迅猛发展的数十年时间里,不断面领着各种新的场景与挑战,例如大数据.大规模集群计算.更复杂的网络环境.多核处理器引起对于高并发的需求,云计算,上千万行的服务器代码-- 那些成熟但上了年纪的语言没能 ...

  4. OpenCV学习笔记(三十一)——让demo在他人电脑跑起来 OpenCV学习笔记(三十二)——制作静态库的demo,没有dll也能hold住 OpenCV学习笔记(三十三)——用haar特征训练自己

    OpenCV学习笔记(三十一)--让demo在他人电脑跑起来 这一节的内容感觉比较土鳖.这从来就是一个老生常谈的问题.学MFC的时候就知道这个事情了,那时候记得老师强调多次,如果写的demo想在人家那 ...

  5. cmake中添加引用动态链接_CMake 添加头文件目录,链接动态、静态库(添加子文件夹)...

    CMake支持大写.小写.混合大小写的命令. 当编译一个需要第三方库的项目时,需要知道: 去哪找头文件(.h),-I(GCC) INCLUDE_DIRECTORIES() 去哪找库文件(.so/.dl ...

  6. linux系统应用学习(三)--- 动态库静态库

    动态库静态库 库文件:一般指第三方提供的可调用的库函数文件,库文件封存的是函数体,即.c文件里面的内容. 动态库      静态库 Windows下:        xx.dll            ...

  7. 硬核拆解动态库静态库

    [Github pages] 动态库与静态库是编程中十分常见的玩意儿,但是如此常见的东西在我真正用心去了解梳理过一遍之后才发现原来这里面有这么多的门道.本文就介绍一波 Linux 平台下,特指 GCC ...

  8. linux库--静态库、动态库

    文章目录 一.分文件编程思想 二.动态库静态库 1.概念介绍 2.静态库的制作和使用 3.动态库的制作和使用 一.分文件编程思想 好处: 分模块的编程思想 例如: 网络 a 超声波b 电机c a.功能 ...

  9. Go语言底层原理剖析

    作者:郑建勋 出版社:电子工业出版社 品牌:博文视点 出版时间:2021-08-01 Go语言底层原理剖析

  10. VS2015编译32位Opencv310(动态库+静态库,文末有下载链接)

    VS2015编译32位Opencv310(动态库+静态库 编译过得,可以直接用的: http://download.csdn.net/download/longzaihuaxia/9802510 之前 ...

最新文章

  1. css3树形图,CSS3 树形堆栈
  2. SourceChangeWarning:验证集上准确率很高,但是测试集上很低
  3. MySQL 数据库时区设置方法,“The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents ...” 问题解决
  4. 那些年我用过的SAP IDE 1
  5. 一些杂七杂八的前端知识1
  6. Java 锁之 CAS
  7. Flask入门之上传文件到本地服务器
  8. TortoiseSVN 不显示图标
  9. 在 Windows 下部署 Go 语言环境
  10. 活动报名 | 苏州工业园区领军人才项目申报宣讲对接会
  11. 解决windows系统无法对docker容器进行端口映射的问题
  12. 对于配置环境变量后的过程~
  13. VS2017适配版的 VA 安装教程
  14. java图片文字识别_java初探Tess4j识别图片文字
  15. MySQL frm、MYD、MYI数据文件恢复
  16. 【Python】用matplotlib函数绘制股票趋势图
  17. ireport oracle,用ireport调用oracle存储过程
  18. 希尔顿集团旗下品牌希尔顿启缤精选酒店在河北廊坊正式开业
  19. 黑客 骚扰欺诈 呼死你之外还假冒给好友打电话
  20. iphonex计算机隐藏功能,iPhoneX如何隐藏小白条 iPhoneX隐藏小白条方法【步骤介绍】...

热门文章

  1. mybatis foreach标签的使用
  2. java 状态模式的实现与应用
  3. 根据ReentrantLock -- 解析AQS原理
  4. JavaEE 保存文件获取绝对路径getResource()和servletContext.getRealPath(/)
  5. 现代浏览器(HTML5)缓存接口文档收集
  6. linux的守护进程init.d和xinetd.d
  7. Suse Enterprise Server 11的安装
  8. 爱尔兰圣三一大学计算机专业硕士,爱尔兰圣三一学院研究生申请要求
  9. ARC097F Monochrome Cat
  10. webpack配置报错WARNING in DefinePlugin Conflicting values for ‘process.env.NODE_ENV‘