下面列出了我在对共享库(动态链接库)编写以及使用时遇到的几个简单问题进行探究和解答:
参考文档:http://www.cnblogs.com/likwo/archive/2012/05/09/2492225.html
1.静态库、动态链接库、共享库有什么区别?
静态库(windows下为.lib,linux下为.a)是在程序编写前就编译到目标程序中了,而动态链接库(windows下为.dll)可以在程序执行的任何时候被动态加载。共享库(linux下为.so)是在程序启动的时候加载到程序中。
1).动态链接库和共享库之间的区别是什么?
我个人认为可以将它们看做是是相同的。如果真的希望了解它们构成上的区别,可以参考这一篇文章:http://www.cnblogs.com/likwo/archive/2012/05/09/2492225.html
2.为什么要用.so文件?
1.由于共享库能被应用程序动态载入内存。所以,应用程序可以在需要时才将.so载入到内存中,这让程序的可维护性变得很高。比如QQ的视频功能需要升级,那么负责编写QQ的程序员不必将QQ所有代码都重写,只需将视频功能相关的.so文件重写即可。
2.生成的.so文件可以认为是一个函数,其他程序就可以在它们的代码中直接调用这些函数来完成相同的工作(相对于其他直接给出源码的函数来讲,这应该是所谓的闭源)。这样的库(代码)可以重复调用,从而减小了代码的编写量,实现了代码的模块化。
3.如何在生成.so/.dll文件?
1.关于生成.dll文件,可以参考我的这一篇简短的介绍:http://www.cnblogs.com/vincentX/p/4798830.html
2.生成.so文件:
举一个简单的例子,我们来实现两个数相加的功能:
1.首先新建2个文件,分别命名为test.h test.c tmp.c
2.将如下代码写入test.h文件中:
1 int add(int, int);
3.将如下代码写入test.c文件中:
1 #include "test.h" 2 3 int add(int a, int b) { 4 return a + b; 5 }
4.将test.c编译成.so文件,bash命令如下:
1 gcc test.c -shared -fPIC -o test.so
shared是生成共享库,-fPIC是声明使用位置无关代码。关于为什么需要加入-fPIC,我会在后面解答。
这时候便在当前目录下生成了一个.so文件。
5.接下来将如下代码写入tmp.c文件中:
1 #include <stdio.h> 2 #include "test.h" 3 4 int main() { 5 printf("Hello world\n"); 6 printf("%d\n", add(2, 3)); 7 return 0; 8 }
6.编译tmp.c:
1 gcc tmp.c -o tmp ./test.so
至此我们可以./tmp来测试一下是否正常使用刚刚写好的.so文件了。执行一下tmp文件:
1 ./tmp
结果如下:
1 Hello world 2 5
说明生成的共享库可以使用了。
我们来做一个小实验:此时把刚刚生成的.so文件删除掉,会有什么样的情况发生呢?
1 rm test.so 2 ./tmp
此时会返回这样一个错误信息:
1 ./tmp: error while loading shared libraries: ./test.so: cannot open shared object file: No such file or directory
找不到tmp中包含的共享库test.so。同时可以解释为,可执行文件的确是在运行前调用的.so文件,(因为此时的hello world也没有被输出)。当我们重新将test.so编译出来以后再执行tmp,便仍然可以正常运行。
4.关于-fPIC?
在linux下制作共享库的“标准做法”是将.so文件编译成位置无关代码,然后生成.so文件。因此我在思考:-fPIC是否是必需的?因为不添加-fPIC的时候也可以正常运行。
关于-fPIC的详细解释可以参见:http://www.cnblogs.com/cswuyg/p/3830703.html
转载请声明出处,谢谢合作。