在演示示例之前,我们先要明白以下几个概念:
1、静态库与动态库的区别:
根据代码被载入的时间不同,linux下库分为两种:静态库和动态库(也叫共享库)。静态库,在编译时,已经被载入到可执行程序中,静态库成为可执行文件的一部分,因此可可执行程序文件比较大。动态库,可执行程序在执行时,才被引用到内存,因此可执行程序文件小。动态库,一个显著特点就是:当多个程序调用同个动态库时,内存中只有一个动态库实例。
2、库命名规范
a)静态库以.a 为后缀,动态库以.so为后缀
b)静态库名字一般是,其中xxx 是库的名字;动态库的名字一般是 其中xxx是库名,majar 是主版本号,minor是副版本号
3、通过ldd查看程序所依赖的共享库
查看vim所依赖的共享库:ldd /usr/bin/vim
4、程序查找动态库的路径
/lib 和 /usr/lib 及 /etc/配置的路径下
有了上面的简单介绍,下面,我们开始给出代码示例了:
1、库源文件:
#include<>
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
void showmsg(const char * msg){
printf("%s \n",msg);
}
void show(int num)
{
printf("The result is %d \n",num);
}
2、库头文件:
#ifndef DEMO_H
#define DEMO_H
extern int add(int a, int b);
extern int sub(int a, int b);
extern void showmsg(const char* msg);
extern void show(int num);
#endif
3、调用库源文件:
#include ""
int main(void){
int a = 3;
int b = 6;
showmsg("3+6:");
show(add(a,b));
showmsg("3-6:");
show(sub(a,b));
return 0;
}
4、编译源文件
[root@localhost demo]# gcc -c
[root@localhost demo]# gcc -c
5、编译可执行程序:
[root@localhost demo]# gcc -o demo
6、查看可执行文件demo并执行
[root@localhost demo]# ls -lh
总计 28K
-rwxr-xr-x 1 root root 5.2K 02-24 10:36 demo
-rw-r--r-- 1 root root 212 02-24 10:06
-rw-r--r-- 1 root root 134 02-24 09:55
-rw-r--r-- 1 root root 1000 02-24 10:10
-rw-r--r-- 1 root root 142 02-24 10:07
-rw-r--r-- 1 root root 1.1K 02-24 10:36
[root@localhost ~]# ./demo
3+6:
The result is 9
3-6:
The result is -3
通过上面的基本,我们的可执行文件demo已经跑起来了,下面,我们主要介绍怎么把封装成库,供其他代码调用,以提高代码的可复用性
静态库:
主要通过ar 把打包成静态库并查看相关文件
[root@localhost demo]# ar rcs
[root@localhost demo]# ls -lh
总计 24K
-rw-r--r-- 1 root root 212 02-24 10:06
-rw-r--r-- 1 root root 134 02-24 09:55
-rw-r--r-- 1 root root 1000 02-24 10:10
-rw-r--r-- 1 root root 1.2K 02-24 10:40
-rw-r--r-- 1 root root 142 02-24 10:07
-rw-r--r-- 1 root root 1.1K 02-24 10:36
ar命令类似于tar命令,起打包的作用。选项r表示将后面的文件列表添加到文件包,如果文件包不存在就创建,
如果文件包中已存在就替换。s是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。
引入静态库,编译可执行文件
[root@localhost demo]# gcc -o demo -static -L . -l demo
注意:gcc生产目标可执行文件,用-l 指定静态库文件时,会自动在静态库名前加lib,在其后加.a 。因此,在引入 静态库时,只用写 demo 即可。-L . 告诉编辑器在当前目录查找函数库。【可以用nm查看目标代码,函数库和可执行程序中具有哪些函数】
查看生成文件demo,删除静态库 ,并执行demo
[root@localhost demo]# ls -lh
总计 568K
-rwxr-xr-x 1 root root 537K 02-24 10:44 demo
-rw-r--r-- 1 root root 212 02-24 10:06
-rw-r--r-- 1 root root 134 02-24 09:55
-rw-r--r-- 1 root root 1000 02-24 10:10
-rw-r--r-- 1 root root 1.2K 02-24 10:40
-rw-r--r-- 1 root root 142 02-24 10:07
-rw-r--r-- 1 root root 1.1K 02-24 10:36
[root@localhost demo]# rm -rf
[root@localhost demo]# ./demo
3+6:
The result is 9
3-6:
The result is -3
通过上面的演示,我们可以很清楚地看到,引导引入静态库之后,可执行程序就不依赖原有静态库了,这是因为,可执行程序中已经包含了静态库。
动态库:
通过gcc生产静态库文件并查看相关文件
[root@localhost demo]# gcc -shared -fPIC -o
[root@localhost demo]# ls -lh
总计 28K
-rw-r--r-- 1 root root 212 02-24 10:06
-rw-r--r-- 1 root root 134 02-24 09:55
-rw-r--r-- 1 root root 1000 02-24 10:10
-rwxr-xr-x 1 root root 4.3K 02-24 10:50
-rw-r--r-- 1 root root 142 02-24 10:07
-rw-r--r-- 1 root root 1.1K 02-24 10:36
-f后面跟一些编译选项,PIC表示与位置无关代码【position independent code】
引入动态库,生成可执行文件demo并执行
[root@localhost demo]# gcc -o demo -L . -l demo
注意:-l demo 表示链接 ,-L . 表示函数库可能在当前目录
[root@localhost demo]# ls -lh
总计 36K
-rwxr-xr-x 1 root root 5.4K 02-24 10:52 demo
-rw-r--r-- 1 root root 212 02-24 10:06
-rw-r--r-- 1 root root 134 02-24 09:55
-rw-r--r-- 1 root root 1000 02-24 10:10
-rwxr-xr-x 1 root root 4.3K 02-24 10:50
-rw-r--r-- 1 root root 142 02-24 10:07
-rw-r--r-- 1 root root 1.1K 02-24 10:36
[root@localhost demo]# ./demo
./demo: error while loading shared libraries: : cannot open shared object file: No such file or directory
为什么,无法成功执行呢?查看可执行程序demo所依赖的动态库
[root@localhost demo]# ldd demo
.1 => (0x0022b000)
=> not found
.6 => /lib/.6 (0x0022c000)
/lib/.2 (0x0019c000)
从提示中,我们可以很清楚地看到,是 没有找到。怎么可以让可执行文件找到该动态库呢?
a)将动态库转移到系统缺省库路径下并执行
[root@localhost demo]# mv /usr/lib
[root@localhost demo]# ./demo
3+6:
The result is 9
3-6:
The result is -3
b)设置加载库环境变量LD_LIBRARY_PATH并执行
[root@localhost demo]# export LD_LIBRARY_PATH=$(pwd)
[root@localhost demo]# ./demo
3+6:
The result is 9
3-6:
The result is -3
c)通过ldconfig 将指定目录下的动态库添加到系统共享中,也就是在缓存文件/etc/中追加指定目录下的共享库
[root@localhost demo]# ldconfig /root/code/c/demo
[root@localhost demo]# ./demo
3+6:
The result is 9
3-6:
The result is -3
附带几个参考资料网址:
gcc中文手册:/gnu/gcc_1.htm
gcc官网手册:/onlinedocs/