Linux下GCC静态动态链接库的使用
Linux下GCC静态动态链接库的使用
本篇讲述Linux下如何利用GCC来制作和使用静态链接库以及动态链接库。
1.静态链接库与动态链接库
早期的共享库以源代码的形式进行,但是由于源代码的方式不利于商业化,即商业公司希望用户使用自己发布的库的同时,不泄露自己的源代码,由此产生了库这样的东西。库主要有以下两种形式:
- 静态链接库
- 动态链接库
- 静态库是出现的比较早的,其本质就是源代码经过只编译不链接形成的中间目标文件(.o文件),通过ar这个工具来归档成.a文件,这个文件就是静态链接库。用户通过.a文件和.h头文件来使用该库,用户拿到这两个文件后,通过.h头文件得知.a文件中的函数原型,然后在自己的代码中包含该头文件,调用其中的函数,在链接的时候链接器会去.a文件中寻找对应的.o文件,最终链接成可执行文件。
- 动态库比静态库出现晚但是效率更高。静态库在被链接时,把已调用的库的代码复制进了可执行程序中,这会使程序占用非常大的空间。当程序重复调用该函数时,这些代码也会被重复复制。动态链接库不是直接复制,而是做了个链接标记,当程序运行时发现自己调用了一个动态链接库中的函数时,会加载这个库到内存中,以后不管多少个程序在调用这个库,内存中只会有一份该库。
2.制作一个静态链接库
假设我们有一个add函数,我们在.h头文件里写上函数声明,在.c源文件里写上函数定义:
add.h:
#include<stdio.h>
int add(int a,int b);
add.c:
#include"add.h"
int add(int a,int b)
{
return a+b;
}
制作这个函数的静态库需要经过两步:
首先利用gcc生成.o文件:
gcc -c add.c add.h
然后使用ar工具生成静态库:
ar -rc libadd.a add.o
这样就制作好了一个名字为libadd.a的静态文件。一般静态库的名字就是libxxx.a,xxx对应xxx.o。
3.使用静态库
我们首先写一个代码来使用上面的add函数:
test.c:
#include"add.h"
int main(int argc,char**argv)
{
int a,b;
printf("现在测试加法,请输入两个整数:\n");
scanf("%d %d",&a,&b);
printf("%d + %d = %d\n",a,b,add(a,b));
return 0;
}
然后使用如下命令来编译链接该文件,其中-ladd指定依赖的静态库名,这里不需要加.a后缀名:
gcc -o test testLib.c -ladd
发现报错:
/usr/bin/ld: cannot find -ladd
collect2: error: ld returned 1 exit status
这是因为当使用-lxxx参数时,链接器会尝试去默认的目录内寻找lxxx.a文件,而当前目录不属于默认目录,所以需要给它指定相应的目录。指定目录使用L参数,具体如下:
gcc -o test test.c -ladd -L.
其中L后面的.表示当前目录。至此编译链接出可执行文件,通过ls -la命令可以看到,生成的test文件大小为8504字节。
4.制作动态链接库
同样的对于上面的add函数,我们使用如下命令来制造对应的动态链接库:
gcc -c add.h add.c -fPIC
gcc -o libadd.so add.o -shared
其中-fPIC是位置无关编译方式来生成.o文件,-shared是按共享库的方式来链接。这样我们就制作出了一个名为libadd.so的动态库文件。
我们再来编译test.c,命令如下:
gcc test.c -ladd -L. -o test
发现test大小为8472字节,比静态库要小,小的不明显是因为这里只有一个函数,并且该函数也只调用了一次。
上一篇: 一些应该注意的问题
下一篇: 部署Django工程应该注意的问题