Linux 动静态库:原理与制作
前言
在日常开发过程中,我们经常会调用库中提供的方法来完成一些操作,比如调用 printf、scanf 等。为什么我们可以使用这些方法?我们自己根本没有实现这些功能,它们是如何被调用的?有这么多的库,编译器怎么知道我要调用哪一个?
接下来将围绕这些问题,详细解释动静态库是什么,如何制作动静态库,以及如何使用动静态库。
动静态库是什么
在日常开发过程中,如果想要在自己的代码中使用别人实现的库或方法,有什么办法吗?
- 直接将别人的源代码拷贝到自己的文件中,再进行调用。
那么如果别人不愿意将源代码公开,但是也希望别人使用自己写的库,怎么办???
学过 C 语言都知道,可执行程序的形成必须经过:预处理、编译、汇编、链接。
其中代码经过编译后会生成汇编代码,此时我们依旧是可以看懂汇编代码的,而经过汇编之后就会生成二进制目标文件,我们是无法阅读二进制文件的。所以根据这个思路,能不能将一个代码经过预处理、编译、汇编后再发送给别人使用?
答案当然是可以的,只要我们有别人的头文件,并且其中声明了调用方法,编译器就会认为有这些方法不会报错,只要在链接时编译器能够找到这些方法即可,关于编译器如何找到在后文会详细介绍。
以上就是动静态库形成的全过程;所以动静态库就是一个已经编译好的源代码文件,通过链接库使得我们可以使用其中的方法。
我们也可以在自己的电脑中查看自己下载的动静态库文件:
在 Linux 中:静态库以 .a 结尾,动态库以 .so 结尾。
在 Windows 中:静态库以 .lib 结尾,动态库以 .dll 结尾;
编写动静态库
在上面,我们已经知道动静态库就是编译好的文件,那么我们也就可以将自己的代码进行编译并将头文件打包形成库。
制作静态库
下面简单实现一个加法函数并形成库:
// add.h
int add(int x, int y);
// add.c
int add(int x, int y) {
return x + y;
}
此时对 add.c 文件进行编译生成二进制目标文件 gcc -c -o add.o add.c,形成目标文件之后还要进行打包 ar 操作,可以多个目标文件放入到一个静态库中,只不过我们这里只有一个。
ar -cr libmath.a add.o 通过 ar 进行打包,-c -r 分别表示创建一个打包文件,如果已经存在打包文件就进行覆盖。
通过 ar 也可以查看一个静态库中有哪些二进制目标文件,通过 -t 选项,-v 选项可以显示详细信息。
注意:在 Linux 下,静态库的命名必须是:lib 开头,.a 结尾,中间才是静态库的名称。
一般我们不会直接见库和自己的程序放在同一个目录下,而是专门设置一个目录存放头文件和库,此处我们也采用这种方式,将头文件、静态库和可执行程序分开:
如上图所示,我们将头文件存放到 include 目录下,将 libmath.a 静态库存放到 目录下。


