一 概述
二 类型
三 语句
四 函数
五 数据
六 内存
七 代码
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5. 动态库
动态库文件独立存在,在程序启动后被动态链接器(ld-linux-x86-64.so)加载。
- 所用接口未变的情况下,更新动态库,无需重新编译调用程序。
创建
准备好库源码文件(.c)以及包含原型的头文件(.h)。
使用 -shared -fPIC
生成动态库。
代码优化发生在编译阶段,链接时不会再次优化,所以要区分 debug 和 release 版本。可分别提供
lib<name>.so
和lib<name>_release.so
两个版本。
$ gcc -g -O0 -Wall -shared -fPIC -o libdemo.so *.c
使用
如生成的库文件不存放到系统目录下,需以 -Wl,-rpath
参数向链接器传递一到多个新搜索路径(冒号分隔)。这些路径将嵌入到可执行文件内。
注意:链接参数要放在
*.c
后面。
$ gcc -g -O0 -I./lib -o test *.c -L./lib -Wl,-rpath=./:./lib -ldemo ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
由于添加了
./
和./lib
搜索路径,所以libdemo.so
可放在这两个相对目录下。如果库文件移动到其他目录(或非当前工作目录),无需重新链接,命令行以LD_LIBRARY_PATH
指定即可。
$ ldd ./test linux-vdso.so.1 (0x00007ffe88fd7000) libdemo.so => ./lib/libdemo.so (0x00007f6595b2c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6595936000) /lib64/ld-linux-x86-64.so.2 (0x00007f6595b38000)
$ LD_LIBRARY_PATH=./xxx ldd ./test linux-vdso.so.1 (0x00007ffc575df000) libdemo.so => ./xxx/libdemo.so (0x00007f105677e000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1056588000) /lib64/ld-linux-x86-64.so.2 (0x00007f105678a000)
插件
还可像插件(plugin)那样在运行期动态装载。
// add.c #include <stdio.h> int add (int x, int y) { return x + y; }
$ gcc -shared -fPIC -o libadd.so add.c $ nm libadd.so 00000000000010f9 T add
使用 dlopen 载入,然后通过符号查找并获取指针。
#include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main (void) { // 载入动态库。 void *handle = dlopen("./lib/libadd.so", RTLD_LAZY); if (handle == NULL) { puts(dlerror()); return -1; } // 函数指针变量。 int (*add)(int, int); // 获取符号地址。 add = dlsym(handle, "add"); if (add == NULL) { puts(dlerror()); return -1; } // 执行后关闭。 printf("%d\n", add(11, 22)); dlclose(handle); return 0; }
$ gcc -o test main.c -ldl $ ./test 33
技巧
为动态库添加一个初始化(init)函数,在载入时执行。
// init.c 放在其他文件也可。 #include <stdio.h> static void __attribute__ ((constructor)) lib_init (void); static void lib_init (void) { printf("Library ready.\n"); return; }
向链接器传递 -Wl,--entry=<func>
设置入口,让动态库可直接执行。
动态链接器路径和文件名,可用 ldd 查看其他程序。
const char service_interp[] __attribute__((section(".interp"))) \ = "/lib64/ld-linux-x86-64.so.2"; void lib_entry (void) { printf("hello, world!\n"); exit(0); }
$ gcc -shared -fPIC -o libdemo.so -Wl,--entry=lib_entry *.c
$ ./libdemo.so hello, world!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论