linux 静态库与动态库

    技术2022-05-11  45

    虽然用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里找不到便会在指定的地方找。  

    最新回复(0)