我们在开发程序提供接口给第三方使用时,为了隐藏函数API的实现细节,最常用的办法便是将这些函数API封装成函数库以后提供给第三方调用。而这种函数库又分为静态库与动态库,所谓静态库就是在程序编译的时候,编译器会将需要调用的函数块直接整合到目标代码中,程序运行时对其不产生依赖。而动态库编译时则不会被整合到可执行文件中,在程序运行的过程中才会从动态库中加载相应的函数。
下面简单介绍一下Linux下创建函数库的几个步骤:
第一步、准备程序源代码:
程序1: hello.h #ifndef HELLO_H #define HELLO_H void hello(const char *name); #endif //HELLO_H 程序2: hello.c #include <stdio.h> void hello(const char *name) { printf("Hello %s!\n", name); } 程序3: cpplive.c #include "hello.h" int main() { hello("CppLive"); return 0; }
第二步、将源代码汇编成.o文件:
gcc -o hello.c
gcc将hello.c汇编成hello.o文件。
第三步、由.o文件创建静态库:
静态库的命名必须遵循一定的规则,否则编译器将无法识别。文件名应以lib为前缀,然后紧跟静态库名以及后缀名.a。例如我们将创建的静态库名为hellocpplive,则静态库文件名为libhellocpplive.a。创建静态库用ar命令。
ar cr libhellocpplive.a hello.o
第四步、利用静态库编译可执行文件:
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。在终端执行如下命令创建静态库:
gcc -o CppLive cpplive.c -L . -lhellocpplive 运行结果: ./CppLive Hello CppLive!
-L.用来指定现在本目录下搜索库,如果没有,会到系统默认的目录下搜索,一般为/lib、/usr/lib下。删除libhellocpplive.a以后再次运行程序,依旧是“Hello CppLive!”,这说明静态库中的公用函数已经被整合到可执行文件CppLive中去了。
第五步、由.o文件创建动态库:
动态库的命名原则跟静态库类似,唯独后缀“.so”不同,例如我们将创建的动态库名为hellocpplive,则动态库文件名为libhellocpplive.so。在终端执行如下命令创建动态库:
gcc -shared -fPCI -o libhellocpplive.so hello.o
为了支持跨平台,所以加上-fPIC 参数。
第六步、利用动态库编译可执行文件:
方法跟原理与静态库类似:
gcc -o CppLive cpplive.c -L. -lhellocpplive 运行结果: ./CppLive ./CppLive: error while loading shared libraries: libhellocpplive.so: cannot open shared object file: No such file or directory
出错了,提示说找不到动态库libhellocpplive.so,程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们既可以将文件 libmyhello.so复制到目录/usr/lib中,也可以将文件 libmyhello.so放置在当前目录并执行“export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./”命令(告诉系统在当前目录寻找库),再次运行程序则正常输出“Hello CppLive!”。
最后,补充一条大家可能会遇到的情况:如果静态库跟动态库的文件名一样,编译器会优先调用动态库。
除非注明,文章均为CppLive 编程在线原创,转载请注明出处,谢谢。