通过最基本的一个头文件、一个函数文件、一个主调文件fun.h,fun.c,main.c来练习动态库与静态库的使用,整理如下:
编辑源代码
头文件:fun.h
#ifndef FUN_H //通过编译预处理命令避免头文件被多次包含
#define FUN_H
#include <stdio.h>
typedef int T; //为类型定义一个别名,如果需要用其他类型只要在此处更改即可
//声明加减乘除的各个函数
T add(T a,T b);
T sub(T a,T b);
T mul(T a,T b);
T div(T a,T b);
#endif
函数文件:fun.c
#include "fun.h"
//实现两个数的加减乘除
T add(T a,T b) //two number addition
{
return a+b;
}
T sub(T a,T b) //two number subtraction
{
return a-b;
}
T mul(T a,T b) //two number multiply
{
return a*b;
}
T div(T a,T b) //two number division
{
return a/b;
}
主函数文件:main.c
#include "fun.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));
printf("div:%d\n",div(a,b));
}
生成目标文件
# gcc -c fun.c
无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序通过gcc先编译成.o文件。
查看详细信息:
#ll
total 32
drwxr-xr-x 2 root root 4096 2013-05-16 03:04 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rw-r--r-- 1 root root 233 2013-05-16 02:36 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 167 2013-05-16 01:39 main.c
可以看到生成了fun.o文件
生成静态库
在linux下,库文件一般放在/usr/lib、/lib下,本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行
静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只有一份该共享库的实例,有助于节省内存,有助于资源共享,简化了软件项目的管理.
# ar -r libmyku.a fun.o
ar: creating libmyku.a
#ll
total 36
drwxr-xr-x 2 root root 4096 2013-05-16 03:09 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rw-r--r-- 1 root root 233 2013-05-16 02:36 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 944 2013-05-16 03:09 libmyku.a
-rw-r--r-- 1 root root 167 2013-05-16 01:39 main.c
可以看到生成了静态库文件libmyku.a
使用静态库
先看一下不使用库的编译运行结果:
# gcc main.c fun.c
# ll
total 44
drwxr-xr-x 2 root root 4096 2013-05-16 03:11 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rwxr-xr-x 1 root root 7278 2013-05-16 03:11 a.out*
-rw-r--r-- 1 root root 233 2013-05-16 02:36 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 944 2013-05-16 03:09 libmyku.a
-rw-r--r-- 1 root root 167 2013-05-16 01:39 main.c
# ./a.out
add:15
sub:5
mul:50
div:2
下面再看一下使用静态库编译运行的结果:
# gcc -o smain main.c libmyku.a
或者通过-L 、-l、参数指定路径与库名来连接:
# gcc -o smain main.c -L. -lmyku
# ll
total 52
drwxr-xr-x 2 root root 4096 2013-05-16 03:20 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rwxr-xr-x 1 root root 7278 2013-05-16 03:11 a.out*
-rw-r--r-- 1 root root 233 2013-05-16 02:36 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 944 2013-05-16 03:09 libmyku.a
-rw-r--r-- 1 root root 167 2013-05-16 01:39 main.c
-rwxr-xr-x 1 root root 7278 2013-05-16 03:20 smain*
# ./smain
add:15
sub:5
mul:50
div:2
静态库的代码在编译过程中载入可执行程序,因此体积与不使用库一样大。
生成动态库
# gcc -shared -fpic -o libmyku.so fun.o
root@ubuntu:/home/psh/uc/day01# ll
total 60
drwxr-xr-x 2 root root 4096 2013-05-16 04:36 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rwxr-xr-x 1 root root 7278 2013-05-16 04:32 a.out*
-rw-r--r-- 1 root root 235 2013-05-16 04:32 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 944 2013-05-16 04:35 libmyku.a
-rwxr-xr-x 1 root root 6694 2013-05-16 04:36 libmyku.so*
-rw-r--r-- 1 root root 186 2013-05-16 04:17 main.c
-rwxr-xr-x 1 root root 7278 2013-05-16 04:36 smain*
使用动态库
# gcc -o dmain main.c libmyku.so
# ll
total 68
drwxr-xr-x 2 root root 4096 2013-05-16 04:40 ./
drwxr-xr-x 3 root root 4096 2013-05-15 21:25 ../
-rw-r--r-- 1 root root 162 2013-05-16 01:21 \
-rwxr-xr-x 1 root root 7278 2013-05-16 04:32 a.out*
-rwxr-xr-x 1 root root 7272 2013-05-16 04:40 dmain*
-rw-r--r-- 1 root root 235 2013-05-16 04:32 fun.c
-rw-r--r-- 1 root root 96 2013-05-16 01:12 fun.cpp
-rw-r--r-- 1 root root 134 2013-05-16 01:40 fun.h
-rw-r--r-- 1 root root 779 2013-05-16 03:04 fun.o
-rw-r--r-- 1 root root 944 2013-05-16 04:39 libmyku.a
-rwxr-xr-x 1 root root 6694 2013-05-16 04:36 libmyku.so*
-rw-r--r-- 1 root root 186 2013-05-16 04:17 main.c
-rwxr-xr-x 1 root root 7278 2013-05-16 04:36 smain*
生成可执行文件成功,由于动态库文件是在可执行文件运行时才加载到内存中,因此生成的可执行文件相对会比较小,由于程序很简单,此处不明显,下面执行一下:
# ./dmain
./dmain: error while loading shared libraries: libmyku.so: cannot open shared object file: No such file or directory
提示加载共享库文件失败,找不到共享库文件
为了让可执行文件顺利找到共享库文件,有以下三种方法:
(1)把共享库文件拷贝到/usr/lib或者/lib目录下,有效性是全局的
#cp libmyku.so /usr/lib
(2修改/etc/ld.so.conf文件,把库所在的路径加到文件的末尾,并执行ldconfig命令刷新,这样,加入的目录正反库都可见
(3)改变环境变量,在LD_LIBRARY_PATH环境变量中加上库所在路径(当前目录"."),只对当前shell终端有效
# LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
# ./dmain