C语言静态库和动态库
之前一直在看文案的解释,没有实操过,所以一直不知道到底是啥意思,直到今天恰巧搞到了一个视频,所以这里记录一下。
静态库制作与使用
制作
代码基础结构:
.
├── include
│?? └── calcute.h
├── lib
├── main.c
└── src
├── add.c
└── multiple.c
3 directories, 4 files
其中:
int add(int,int);
int multiple(int,int);
#include "calcute.h"
int add(int a,int b){
return a+b;
}
#include "calcute.h"
int multile(int a,int b){
return a*b;
}
#include <stdio.h>
#include "calcute.h"
int main(int argc, char const *argv[])
{
printf("2+3=%d\n",add(2,3));
printf("2*3=%d\n",multiple(2,3));
return 0;
}
下面就是具体的步骤了:
生成.o文件
所谓.o 文件就是二进制文件,也就是库的原型。
cd src
gcc *.c -c -I ../include/
-
-I 就是增加头文件的搜索路径 -
-c 就是仅编译不链接
具体gcc参数见这里
然后这样就产生了两个add.o 和multiple.o 文件了,下一步就是打包。
打包.o文件
所谓打包就是将这两个二进制.o 文件合并在一起。打包用的命令就是ar :
ar rcs libcaculate.a *.o
然后就是将这个打包好的静态文件随便放哪里,但是按照一般习惯,是放在lib 目录下的,所以这里移动一下:
mv ./libcaculate.a ../lib/
静态库使用
之后就是在main.c 中使用这个编译好的静态库了。
cd ../
gcc main.c -I ./include/ -L ./lib -l caculate -o main
在上面中使用到的gcc 参数含义为:
动态库制作与使用
如果不讲动态库,那么你很难理解,什么叫动态库,其和静态库有什么区别。
还是上面的代码,只不过这一次我们将其制作为动态库的形式。
生成.o文件
还是在src 目录下先制作.o 文件:
gcc *.c -c -fpic -I ../include/
- 加上了一个
-fpic 的参数,代表用来生成与位置无关的文件。
打包.o文件
上面打包静态库使用了ar 命令,这里是使用gcc 命令。
gcc -shared -o libmycaculate.so *.o
使用
这里就很有意思,也是和静态库最大的不同,假设这里还是像使用静态库一样的使用静态库:
gcc -I ./include/ -L ./lib/ -l mycaculate main.c -o main
编译是成功的,只是你尝试运行一下:
./main
./main: error while loading shared libraries: libmycaculate.so: cannot open shared object file: No such file or directory
说人话就是找不到这个动态库,是不是超级生气,我告诉你了啊,在lib 目录下的libmycaculate.so 啊,可是操作系统愣是找不到,真是个傻子。
奈何在不如它牛逼之前智能照着它的规矩来,可以使用ldd 命令查看当前的main 文件调用了哪些动态库:
ldd main
linux-vdso.so.1 (0x00007ffc6c1f5000)
libmycaculate.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f2c8fab3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2c8fe78000)
其中的重点:
libmycaculate.so => not found
所以下面的重点就是如何解决这个动态库找不到的问题。
动态库配置
参考博客
方式1:修改 /etc/ld.so.conf
我是Centos 操作系统,不知道别的操作系统怎么样的。把上面的目录打开,就是一句很简单的话:
include ld.so.conf.d/*.conf
就像Nginx 配置文件一样,支持以文件的形式来配置不同的动态库,那我们就简单搞一个calcuate.conf :
在其中加一下我们的动态库路径:
vim caculate.conf
/home/root/example1/lib
这是我的路径,然后保存退出,接下来就是要让我们的配置生效:
ldconfig
然后重新运行一下刚才生成的文件,就运行正确了。
方式2:修改环境变量 PATH
但是这个方法没有成功,我不知道为啥。。。。。。
总结
从上面的结构就能看到,静态库就是在生成可执行文件的时候就打包在里面了,而动态库则是在运行的时候才去找库文件。
|