c/c++ 动态库与静态库的制作和使用
静态库的用法
静态库的文件名 libxxx.a -->对应windows的.lib文件
做静态库的命令:
ar rcs libxxx.a file1.o file2.o file.o
使用静态库:
gcc main.c -l lib/ -lxxx
注意:-l的作用是告诉gcc你的libxxx.a放在了哪个目录里;-l的作用是告诉gcc使用哪个静态库。
举个例子,目录结果如下:
├── include │ └── head.h ├── lib │ ├── main.c └── src ├── add.c ├── mul.c └── sub.c
head.h
int add(int, int); int sub(int, int); int mul(int, int);
add.c
int add(int a, int b){ return a + b; }
sub.c
int sub(int a, int b){ return a - b; }
mul.c
int mul(int a, int b){ return a * b; }
- 步骤1:在src目录执行下面的命令,生产.o文件
gcc -c *.c
执行后,在src目录下生产了add.o,sub.o,mul.o三个文件
- 步骤2:在src目录执行下面的命令,生产libcalc.a文件
ar rcs libcalc.a *.o
执行后,在src目录下生产了libcalc.a
- 步骤3:在src目录执行下面的命令,把libcalc.a移动到上层的lib文件夹
mv libcalc.a ../lib/
执行后,在lib文件夹出现了libcalc.a
main.c
#include <stdio.h> #include "head.h" int main(){ int a = 10, b = 5; printf("add:%d\n",add(a, b)); printf("sub:%d\n",sub(a, b)); printf("mul:%d\n",mul(a, b)); }
- 步骤4:在src的上层目录,执行下面命令生产a.out文件
gcc main.c -i include/ -l lib/ -lcalc
-i:指定头文件所在的路径
- -l:指定静态库文件所在的路径
-l:指定使用哪个静态库
最后目录结构如下:
├── a.out ├── include │ └── head.h ├── lib │ └── libcalc.a ├── main.c └── src ├── add.c ├── add.o ├── mul.c ├── mul.o ├── sub.c └── sub.o
动态库的用法
动态库的文件名 libxxx.so -->对应windows的.dll文件
编译时,需要加【-fpic】选项。
它的作用是,编译出与位置无关的代码。因为动态库在加载到下图的共享库区的时候,不一定加载到哪个位置,
所以加了-fpic后,就记录了每个函数相对于这个动态库头地址的偏移,加载后动态库在内存里的头地址是知道的,又知道了每个函数相对于头的偏移量,自然而然地就能够找到每个函数在内存里的位置了。
做静态库的命令(-shared):
gcc -shared -o libcalc.so *.o
用【ldd】命令查看编译出来的可执行文件文件
ldd a.out
结果如下:
ys@ys-virtualbox:~/lianxi1$ ldd a.out linux-vdso.so.1 (0x00007ffdebd2d000) libcalc.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3b3e7ee000) /lib64/ld-linux-x86-64.so.2 (0x00007f3b3ede1000)
发现【libcalc.so => not found】
解决办法1:把做好的动态库libcalc.so拷贝到【/lib】或者【/usr/lib】下,也可以用ln做软硬连接:把当前目录下的lib目录下的libcalc.so链接到/lib下
sudo ln -s ./lib/libcalc.so /lib/
结果如下:
发现软连接是红色的,也就是不能使用的意思,错误在于./lib/libcalc.so这个路径是不存在的,原因在于上面的命令使用的是相对路径,改成绝对路径就ok了,命令如下:
sudo ln -s ~/lianxi1/lib/libcalc.so /lib/
结果如下:
发现软连接是绿色的了,说明库可以使用了,开森啊。
再用【ldd】命令查看编译出来的可执行文件文件
ldd a.out
结果如下:
ys@ys-virtualbox:~/lianxi1$ ldd a.out linux-vdso.so.1 (0x00007ffe783c4000) libcalc.so => /lib/libcalc.so (0x00007f35fd6ae000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f35fd2bd000) /lib64/ld-linux-x86-64.so.2 (0x00007f35fdab2000)
发现【libcalc.so】已经被找到了,好开心。
但是这种方法不推荐使用。理由是,放在了系统的动态库目录里,容易和别的库重复,发生冲突。
解决办法2:告诉系统,给我加一个动态库的路径,这个是最好的办法。
- 首先编辑/etc/ld.so.conf文件,添加你自己的库的路径
- 然后,执行:【sudo ldconfig】,就ok了。
静态库和动态库的特点:
- 静态库:
- 编译的时候,直接把静态库的代码直接编译到目标文件
- 执行速度快,不需要在执行的时候加载动态库
- 库文件修改后,必须重新编译使用库的代码
- 动态库
- 编译的时候,不把静态库的代码直接编译到目标文件
- 执行速度慢,在执行的时候需要加载动态库
- 库文件修改后,一般不需要重新编译使用库的代码,只有在库的接口改变时,才需要重新编译使用库的代码。
上一篇: 类和对象的介绍
下一篇: SpringBoot之旅第五篇-数据访问