编译、链接、运行,一气呵成:
文章插图
2.2.5 ar 命令参数介绍制作静态库时所使用的指令
$ ar rcs libcalc.a add.o sub.o mult.o div.o
共有三个参数:- -c:创建一个库,不管库是否存在,都将创建 。这个很好理解,就不做过多的解释了 。
- -r:在库中插入(替换)模块。默认新的成员添加在库的结尾处,如果模块名已经在库中存在,则替换同名的模块 。
- -s:创建目标文件索引,这在创建较大的库时能加快时间 。
假设现在有了新的需求,需要静态库 libcalc.a 提供除法运算的功能模块 , 该怎么操作呢?
首先我们需要新建一个除法运算的源文件 div.c:
#include <stdio.h>double divide(int a, int b){return (double)a / b;}
并通过汇编操作生成目标文件 div.o 。接下来我们可以通过 -r 参数将除法运算的模块添加到静态库中:
$ ar -r libcalc.a div.o
。并且要在 head.h 中增加对除法运算的声明:
#ifndef _HEAD_H_#define _HEAD_H_// Otherdouble divide(int a, int b);#endif
参数 -s 的详细解释在获取一个静态库的时候,我们可以通过
$ nm -s libcalc.a
来显示库文件中的索引表:文章插图
而索引的生成就要归功于 -s 参数了 。
如果不需要创建索引 , 可改成 -S 参数 。2.2.6 其他命令介绍
如果 libcalc.a 缺少索引 , 可以使用$ ranlib libcalc.a
指令添加 。
# 显示库文件中有哪些目标文件,只显示名称$ ar t libcalc.a# 显示库文件中有哪些目标文件,显示文件名、时间、大小等详细信息$ ar tv libcalc.a# 显示库文件中的索引表$ nm -s libcalc.a# 为库文件创建索引表$ ranlib libcalc.a
2.3 动态库2.3.1 动态库简介在 Linux 中动态库以 lib 作为前缀、以 .so 作为后缀,形如 libxxx.so(其中的 xxx 是库的名字,自己指定即可) 。相比于静态库,使用动态库的程序,在程序编译时并不会链接到目标代码中,而是在运行时才被载入 。不同的应用程序如果调用相同的库,那么在内存中只需要有一份该共享库的实例,避免了空间浪费问题 。同时也解决了静态库对程序的更新的依赖,用户只需更新动态库即可 。2.3.2 动态库的生成生成动态库是直接使用 gcc 命令,并且需要添加 -fpic 以及 -shared 参数:
- -fpic 参数的作用是使得 gcc 生成的代码是与位置无关的 , 也就是使用相对位置 。
- -shared 参数的作用是告诉编译器生成一个动态链接库 。
文章插图
2.3.3 动态库的制作举例还是以上述程序 add.c、sub.c、mult.c 为例:
# 第一步:将源文件 add.c、sub.c、mult.c 进行汇编,得到二进制目标文件 add.o、sub.o、mult.o$ gcc -c -fpic add.c sub.c mult.c# 第二步:将得到的 .o 文件打包成动态库$ gcc -shared add.o sub.o mult.o -o libcalc.so# 第三步:发布动态库和头文件1. 提供头文件 head.h2. 提供动态库 libcalc.so
至于为什么需要提供头文件,在讲解静态库时已经做了说明,此处不再赘述 。2.3.4 动态库的使用head.h
#ifndef _HEAD_H_#define _HEAD_H_int add(int a, int b);int subtract(int a, int b);int multiply(int a, int b);#endif
main.c#include <stdio.h>#include "head.h"int main(){int a = 20;int b = 12;printf("a = %d, b = %d\n", a, b);printf("a + b = %d\n", add(a, b));printf("a - b = %d\n", subtract(a, b));printf("a * b = %d\n", multiply(a, b));return 0;}
和静态库的链接方式一样,都是通过指令$ gcc main.c -o main -L ./ -l calc
来进行链接库操作 。gcc 通过指定的动态库信息生成了可执行程序 main , 但是可执行程序运行却提示无法加载到动态库:
./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
这是怎么回事呢?
2.3.5 解决动态库加载失败的问题首先来看一下不同库的工作原理:
- 静态库如何被加载:
- 在程序编译的最后一个阶段也就是链接阶段,提供的静态库会被打包到可执行程序中 。
- 当可执行程序被执行,静态库中的代码也会一并被加载到内存中,因此不会出现静态库找不到无法被加载的问题 。
- 动态库如何被加载:
推荐阅读
- java中GC的日志认识详解
- 我的世界指令附魔攻略(我的世界附魔1000级的指令)
- JUC中的AQS底层详细超详解
- 图文详解 微服务 Zipkin 链路追踪原理
- 唐人街探案3剧情详解_唐人街探案3讲了什么剧情
- C++之值传递&指针传递&引用传递详解
- 非常全面 Dubbo 原理和机制详解
- 未知暗殿走法路线详解(未知暗殿怎么走视频)
- JWT基础概念详解
- Go | 基本数据类型详解