库的概念
- 库是一个二进制文件,包含的代码可被程序调用
- 标准C库、数学库、线程库......
- 库有源码,可下载后编译;也可以直接安装二进制包
库的知识
- 库是事先编译好的,可以复用的代码
- 在os上运行的程序基本上都要使用库。使用库可以提高开发效率
- Windows和Linux下库文件格式不兼容
- Linux下包含静态库和共享库
静态库的特点
编译(链接)时把静态库中相关代码复制到可执行文件中
优点:
- 程序中已包含代码,运行时不再需要静态库
- 程序运行时无序加载,运行速度更快
缺点:
- 占用更多的磁盘和内存空间
- 静态库升级后,程序需要重新编译链接
静态库的创建
- 确定库中函数的功能、接口
- 编写库源码(.c文件)
Demo:
hello.c
#include <stdio.h> void hello(void) { puts("Hello World"); return; }
编译生成目标文件
$ gcc -c hello.c
创建静态库(库文件名要求 以lib开始 以.a结束 中间的部分叫库名)
$ ar crs libdemo.a hell.o
查看库中包含的符号
$nm libdemo.a
>>
libhello.a(main.o):
0000000000000000 T _hello
U _puts
调用静态库
Demo:
test.c
// 声明函数原型 void hello(void); int main(int argc, char *argv[]) { // 调用函数 hello(); return 0; }
编译:(-L 库的搜索路径 -l 库名 进行链接)
$ gcc -o test test.c -L . -l hello
或
$ gcc main.c lib.a –o main.out
小结
①编译静态库源码:gcc –c lib.c –o lib.o
②生成静态库文件:ar –q lib.a lib.o //将 lib.o 与其他文件打包到 lib.a 中
③使用静态库编译:gcc main.c lib.a –o main.out
共享库的特点
编译(链接)时仅记录用到那个共享库中的哪个符号,不复制共享库中相关代码
优点:
- 程序不包含库中代码,尺寸小
- 多个程序可共享一个库
缺点:
- 程序运行时需要加载库
- 升级方便,无序重新编译程序
共享库的创建
- 确定库中函数的功能、接口
- 编写库源码
Demo:
hello.c
#include <stdio.h> void hello(void) { puts("Hello World "); return; }
bye.c
#include <stdio.h> void hello(void) { puts("bye "); return; }
编译生成目标文件
$ gcc -c -fPIC hello.c bye.c
创建共享库(库文件名要求 以lib开始 以.a结束 中间的部分叫库名 、.x表示数字 一般用于区分版本)
$ gcc -shared -o libdeme.so.x hello.o bye.o
为共享库创建符号链接(库文件名要求 以lib开始 以.a结束 中间的部分叫库名、后面跟的符号链接不能加.x后缀)
$ ln -s libdemo.so.1 libdemo.so
创建动态库头文件 (可以不做 在调用前声明也可以)
void hello(){}; void bye(){};
使用动态库
test.c
#include "demo.h" void bye(void) { hello(); bye(); return; }
编译
$ gcc-o test test.c -L . -l demo
执行出错
error while loading shared libraries ....No such file or directory
添加共享库的加载路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
小结
①编译动态库源码:gcc –shared dlib.c –o dlib.so
②使用动态库编译:gcc main.c -ldl –o main.out
如何找到共享库
- 把库拷到/usr/lib 和 /lib目录下(不推荐)
- 在LD_LIBRARY_PATH环境变量中添加库的环境变量
- 添加/etc/ld.so.conf/*.conf文件,执行ldconfig刷新
- 例如:
$ vim /etc/ld.so.conf/demo.conf
/path
$ ldconfig