什么是库文件?
开发者把写好的功能代码封装到一个文件里面,提供接口给用户使用,该封装好的文件就是库文件!!!例如我们熟悉的计算机视觉开源库(OpenCV),里面集成了大量写好的功能函数库,用户可以通过相应接口调用。
库文件的作用?
1.用户在使用库文件的时候是看不到源代码的,这样可以防止源代码的泄露!!
2.库文件在编译的时候,是不会编译进代码的,只有运行的时候会才链接过去,这样可以节省空间,提高代码的复用效率。
3.库文件还有一个好处是,方便用户更新接口。
在Linux系统中看到的所有以 .so 或 .a 结尾的文件都是库文件!!!
- 例如,在Linux上查看OpenCv的库文件(OpenCv需要自己安装)
那么,在这里要打个问号了?我们平时使用的是库文件,为什么这些库文件又要再搞个软链接出来呢?那是因为库文件的版本经常会升级、更新;采用链接的方式,方便用户的程序升级。
//例如对动态库libopencv_video.so.3.4.3 的使用,链接出来之后,进程只需要找到libopencv_video.so这个链接文件即可,由它再去寻找我们最终的动态库libopencv_video.so.3.4.3 ;即使该动态库升级更新了,也不影响用户的程序代码
lrwxrwxrwx 1 root root 22 4月 19 10:27 libopencv_video.so -> libopencv_video.so.3.4
lrwxrwxrwx 1 root root 24 4月 19 10:27 libopencv_video.so.3.4 -> libopencv_video.so.3.4.3
-rw-r--r-- 1 root root 4047848 4月 19 09:59 libopencv_video.so.3.4.3
动态库的制作步骤:
- 编写源代码与接口说明文件
- 把所有的 .c 文件生成 .o 文件
- 把所有的 .o文件打包到动态库中
举个简单的例子:
//1. 编写源代码 add.c文件
#include <stdio.h>
int add(int a,int b)
{
return a+b;
}
//2. 编写接口说明文件 add.h
#ifndef _ADD_H
#define _ADD_H
//功能函数,实现两个整型数据的相加
int add(int a,int b);
#endif
//3. 将 add.c编译生成add.o
gcc -fPIC -c add.c -o add.o //参数-fPIC的作用 :使用相对地址,提高库的兼容性
//4. 将add.o打包成动态库
gcc -shared -fPIC -o libadd.so add.o
使用动态库:
- 用户编写自己的程序代码,在代码中调用动态库的接口函数
- 编译程序代码,不过编译过程中动态库并不会加载到程序中
- 在运行程序时动态库才会被调用
//1. 用户编写代码 main.c
#include <stdio.h>
#include "add.h" //添加动态库接口文件
int main()
{
int x=10,y=20;
printf("x+y=%d\n",add(x,y)); //调用动态库中的功能函数
return 0;
}
//2. 编译程序
gcc main.c -o main -I./add -L./add -ladd
参数说明:
-L 指定库文件的所在路径
-I 指定库文件的头文件所在路径
-ladd 链接库 (-l+库名称)
静态库的制作
- 编写源代码与接口说明文件
- 把所有的 .c 文件生成 .o 文件
- 把所有的 .o文件打包到静态库中
举个例子:
//1. 编写源代码 sub.c文件
#include <stdio.h>
int sub(int a,int b)
{
return a-b;
}
//2. 编写接口说明文件 add.h
#ifndef _ADD_H
#define _ADD_H
//功能函数,实现两个整型数据的相j减
int sub(int a,int b);
#endif
//3. 将 sub.c编译生成sub.o
gcc -fPIC -c sub.c -o sub.o //参数-fPIC的作用 :使用相对地址,提高库的兼容性
//4. 将sub.o打包成静态库
ar -rc libsub.a sub.o