库的定义
当使用别人的函数时除了包含头文件以外还需要有库
头文件也就是.h结尾的文件,其中包含:宏定义、结构体、联合体、枚举的定义、函数声明、重命名、其他头文件、条件编译、外部引用
库:把一些常用的函数的目标文件打包在一起,提供相应的函数接口,便于程序员使用。本质上来说库是一种可执行代码的二进制形式文件。
库的分类
静态库和动态库,本质区别时代码载入的时刻不同。
静态库
静态库在程序编译时会被复制到目标代码中, 以.a结尾。
优点:程序运行的时候不再需要静态库,运行时无需加载库,运行速度快,可移植性好。
缺点:静态库中的代码复制到了程序中,因此体积较大;静态库升级后,程序需要重新编译链接。
动态库
动态库是在程序运行时才被载入代码中。也叫共享库,以.so结尾。
优点:程序在执行时加载动态库,代码体积小;程序升级更简单;
不同应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
缺点:运行时还需要动态库的存在,移植性较差。
静态库的制作
1、将源文件编译生成目标文件xx.o
gcc -c fun.c -o fun.o
2、创建静态库用ar命令,将很多.o文件转换成一个.a文件
ar crs libmyfun.a fun.o
3、静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a
4、测试使用静态库:
gcc main.c -L. -lmyfun //-L指定库的路径 -l指定库名
执行:./a.out
例子:
动态库制作
1、用gcc创建共享库
gcc -fPIC -c fun.c -o fun.o //-fPIC创建与地址无关的编译程序
gcc -shared -o libfun.so fun.o
2、测试使用动态库
gcc main.c -lfun
执行:./a.out
动态库的常见错误和解决方法
常见错误:可以正常编译通过,但是运行时报错error while loading shared libraries: libmyadd.so: cannot open shared object file: No such file or directory
原因:当加载动态库时,系统会默认从/lib或/usr/lib路径下查找库文件,所以需要把库拷贝到/usr/lib或者lib目录下,编译时不用-L加路径了,直接gcc main.c -lfun就可以了
解决方法(有三种):
1、把库拷贝到/usr/lib和/lib目录下。(此方法编译时不需要指定库的路径)
2、在LD_LIBRARY_PATH环境变量中加上库所在路径。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
(终端关闭,环境变量就没在了)
3、添加/etc/ld.so.conf.d/*.conf文件。
把库所在的路径加到文件末尾,并执行ldconfig刷新
sudo vi xx.conf
添加动态库存在的路径,如:/home/hq/work/lib
-L路径:指定库的路径
-l库名:指定库名
-I(大写i):指定头文件路径,默认查找路径/usr/include
#include <stdio.h> //从系统路径下查找头文件
#include "head.h" //从当前路径下查找此头文件
ldd 可执行文件名:查看链接的动态库
注意:
同名的静态库和动态库:默认优先使用动态库,如果想使用静态库 需要在后面加 -static,这是内核规定的。