一前言.
在windows下,静态链接库文件后缀是.lib, 动态链接库文件后缀是.dll
在linux下,静态链接库文件后缀是.a, 动态链接库文件后缀是.so
二.linux下的静态链接库(暂不说windows下的dll)
1.新建一个printf.c 和 printf.h文件,在printf.c文件写上相应的测试函数,以及在.h文件中声明。
2.新建一个makefile文件,在makefile中写:
all:
gcc printf.c -o printf.o -c
ar -rc libprintf.a printf.o
clean:
rm -rf *.o *.a
备注:-o参数用于指定输出(out)文件名。不用-o的话,一般会在当前文件夹下生成默认的a.out文件作为可执行程序。
-c参数表示只编译(compile)源文件但不链接,会把.c或.cc的c源程序编译成目标文件。咱们这里是生成库文件,所以也不需要链接。
使用ar工具进行打包成.a归档文件, -r将文件插入备存文件中, -c建立备存文件。
这里注意 库名不能随便乱起,一般是lib+库名称,后缀名是.a表示是一个归档文件,制作出来了静态库之后,发布时需要发布.a文件和.h文件。
至此静态链接库就制作完成。那如何引用它呢?
1.我们将上面制作好的libprintf.a文件和printf.h复制到一个新的test文件夹中。再新建一个test.c文件和一个makefile文件。
注意:test.c中头文件应包含printf.h------>#include "printf.h" //(注意双引号)
然后写好main函数,在main函数中调用printf.c中写好的测试函数。
2.接下来就是写makefile
`
all:
gcc test.c -lprintf -L.
#注意-L后面的.
clean:
rm -rf *.o *.out
`
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。
-L .,表示将当前目录作为第一个寻找库文件的目录, 寻找的顺序是:./–>/lib–>/usr/lib–>/usr/local/lib
注意:编译时,必须得告诉编译器静态链接库的名字和路径(没告诉的话会去默认路径下查找),这点也很容易理解。
3.编译后 执行a.out文件,即输出printf.c中测试函数的内容,整个下来就是静态链接库的制作和使用。
三.linux下的动态链接库
1.同样新建一个printf.c printf.h 和makefile
2.makefile中编写如下:gcc printf.c -o printf.o -c -fPIC<br/>gcc -o libprintf.so printf.o -shared <br/>
-fPIC参数是位置无关码,-shared参数是按照共享库的方式来链接。
此时生成的libprintf.so文件即动态链接库文件,那么在发布的时候,发布libprintf.so和printf.h文件即可
3.同样新建一个test文件,将libprintf.so与printf.h文件复制进去,新建一个test.c与makefile文件。
4.makefile写法与静态链接库一致
`
all:
gcc test.c -lprintf -L.
#注意-L后面的.
clean:
rm -rf *.o *.out
`
但是由于静态链接与动态链接实现的机制不同,具体哪些不同,请自行百度搜索,很多。
这里直接去执行./a.out是执行不成功的
报错误:
error while loading shared libraries: libprintf.so: cannot open shared object file: No such file or directory
原因是使用动态链接库时,需要临时加载动态链接库,而不是在编译时将库里面的内容加载出来,编译到一起。这是与静态链接库不同的地方。所以,它这里找不到库文件在哪里,那么有一下几种解决办法:
(1)将libprintf.so放到固定目录下就可以了,这个固定目录一般是/usr/lib目录。 cp libprintf.so /usr/lib即可
(2)使用环境变量LD_LIBRARY_PATH。操作系统在加载固定目录/usr/lib之前,会先去LD_LIBRARY_PATH这个环境变量所指定的目录下去寻找,如果找到就不用去/usr/lib下面找了,如果没找到再去/usr/lib下面找。所以解决方案就是将libprintf.so所在的目录导出到环境变量LD_LIBRARY_PATH中即可。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: + 文件所在的路径。
5.再去执行a.out即可执行成功。
四.总结
1.咱们注意到静态链接库与动态链接库中 test文件夹中makefile,都有一句gcc test.c -lprintf -L,注意这个-lprintf参数,假如在文件夹中,又有静态链接库,又有动态链接库,那编译器该如何选择呢? 答案是会优先选择动态链接库文件。
2.还有个nm命令也很有用,它可以用来查看一个.a或者.so文件中都有哪些符号,简单来说就是看有哪些函数。
3.ldd命令(动态链接库):作用是可以在一个使用了共享库的程序执行之前解析出这个程序使用了哪些共享库,并且查看这些共享库是否能被找到,能被解析(决定这个程序是否能正确执行)。
原文地址:http://blog.51cto.com/13403824/2161668