`
isiqi
  • 浏览: 16073128 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

linux 静态库与动态库

阅读更多
虽然用Linux已有些年头了,但对于Linux下的静态库以及动态库生成和连接了解的并不多。所以今天对其做了个系统学习。
1,简单程序
如果我们有a.c,b.c,包含函数a(),b(),都只是输出函数的调用,t.c里调用a(),b().如下:
a.c:
void a(void) {
printf("Call %s", __FUNCTION__);
}
b.c:
void b(void) {
printf("Call %s", __FUNCTION__);
}
t.c:
int main(void) {
a();
b();
}
我们可以通过:gcc -o t t.c a.c b.c生成一个可执行程序t,运行t我们可以行到以下结果:
Call a
Call b
这里我们除了libc,ld动态的连接,没有对其他任何库的连接,我们可以通过ldd查看:
ldd ./t
libc.so.6 => /lib/tls/libc.so.6 (0x00724000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x0067c000)
2,静态库
我们在参与项目时,很多时候都是分模块进行,模块与模块之间提供接口。而模块在提供的形式上一个比较简单的方式就是静态库。比如,A,B,C三个模块,A要调用B,B要调用C,而B,C有很多源程序,且复杂庞大,那么把B,C分别做成一个静态库libB.a,libC.a,那么A在使用时只要将libB.a和libC.a连接进去就可以了。
还拿上个例子来说,我们可以将a.c和b.c放入一个静态库libab.a里,而在编译t.c时只要将libab.a连接进去就可以了。如:
gcc -c a.c b.c这样会生成a.o,b.o两个对象文件,把这两个文件打包成一个静态库libab.a:
ar -cr libab.a *.o便会生成一个libab.a的文件。我们可以通过
ar -t libab.a查看libab.a里有些什么,输出结果是:
a.o
b.o
现在我们有一个包含有t.c里调用的a(),b()这两个函数的静态库libab.a,那么在编译t.c时我们可以这样来做到:
gcc -o t t.c libab.a
也可以通过gcc的-L和-l参数来指定库的位置,因为有时候写出库的整个路径总是很麻烦的:
gcc -o t t.c -L./ -lab
-L说明到某个目录去查找-l所指定的静态库,gcc会把-lab扩展成libab.a。
3,动态库
动态库是一种在运行时才装入内存的库文件,它为插件开发,功能扩展等等提供了便利。和静态库不同的时,连接动态库并不会将动态库里的代码连接到程序里,而是在运行时动态连接。所以动态生成的程序较静态的小。当然你得找个地方把动态库放好。
一般来说动态库都放在/lib,/usr/lib目录里,你也可以指定到哪些目录下去找你的库。
还是上个例子,我们可以将a.c和b.c生成一个动态库:
gcc -fpic -shared -o libab.so a.c b.c
生成libab.so后:
gcc -o t t.c libab.so生成了一个动态连接的可执行程序t。
但是我们在运行t的时候却报错了:
./t: error while loading shared libraries: libab.so: cannot open shared object file: No such file or directory
找不到动态库libab.so。当然,这是因为ld在找/lib,/usr/lib目录里的动态库时,无法找到libab.so。如果我们把libab.so复制到/lib或/usr/lib目录下一切就OK了。
当然你也可以指定某个目录去查找动态库,这要通过LD_LIBRARY_PATH达到这个目标。
我们可以这样做,把当前编译t的目录加入到LD_LIBRARY_PATH里去:
LD_LIBRARY_PATH=./
export LD_LIBRARY_PATH
这样的话,如果在/lib,/usr/lib里找不到便会在指定的地方找。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics