是否存在编译器标志允许共享库调用打开它的共享库的函数?
问题:无需显式传递函数指针,让a.so调用b.so中的b_util函数
我需要实现从a()函数中调用b_util(),但不想通过显式传递b_util()的函数指针给a.c的方式来实现。我尝试使用-rdynamic编译标志(类似让共享库调用主可执行文件函数的场景),但编译a.c或b.c时添加该标志后,依然出现相同的运行时错误,想了解正确使用该标志的方法。
当前使用的编译命令:
gcc c.c -o c.out && gcc b.c -o b.so -shared -fPIC && gcc a.c -o a.so -shared && ./c.out
运行后输出错误:
dlopen: ./a.so: undefined symbol: b_util
相关代码
a.c
void b_util(void); void a(void) { b_util(); }
b.c
#include <dlfcn.h> #include <stdio.h> #include <stdlib.h> void assert_dl(void *p, char *fn_name) { if (!p) { fprintf(stderr, "%s: %s\n", fn_name, dlerror()); exit(EXIT_FAILURE); } } void b(void) { void *dll = dlopen("./a.so", RTLD_NOW); assert_dl(dll, "dlopen"); void (*a)(void) = dlsym(dll, "a"); assert_dl(a, "dlsym"); a(); } void b_util(void) { printf("b_util\n"); }
c.c
#include <dlfcn.h> #include <stdio.h> #include <stdlib.h> void assert_dl(void *p, char *fn_name) { if (!p) { fprintf(stderr, "%s: %s\n", fn_name, dlerror()); exit(EXIT_FAILURE); } } int main(void) { void *dll = dlopen("./b.so", RTLD_NOW); assert_dl(dll, "dlopen"); void (*b)(void) = dlsym(dll, "b"); assert_dl(b, "dlsym"); b(); }
解决方案
问题核心是:加载a.so时,b.so中的b_util符号未被暴露给a.so解析。需要调整编译选项和动态加载标志实现符号共享:
- 修改
b.c的编译命令:添加-rdynamic,让b.so的符号导出到动态符号表,允许后续加载的库访问 - 修改
b.c中的dlopen调用:添加RTLD_GLOBAL标志,让a.so加载时能访问已加载的全局符号(即b.so中的b_util)
修改后的代码和命令
修改后的b.c(仅改动dlopen行)
#include <dlfcn.h> #include <stdio.h> #include <stdlib.h> void assert_dl(void *p, char *fn_name) { if (!p) { fprintf(stderr, "%s: %s\n", fn_name, dlerror()); exit(EXIT_FAILURE); } } void b(void) { // 添加RTLD_GLOBAL标志 void *dll = dlopen("./a.so", RTLD_NOW | RTLD_GLOBAL); assert_dl(dll, "dlopen"); void (*a)(void) = dlsym(dll, "a"); assert_dl(a, "dlsym"); a(); } void b_util(void) { printf("b_util\n"); }
正确的编译运行命令
gcc c.c -o c.out && gcc b.c -o b.so -shared -fPIC -rdynamic && gcc a.c -o a.so -shared && ./c.out
原理说明
-rdynamic:让编译器将b.so中的全局符号(如b_util)加入动态符号表,使得这些符号可以被后续动态加载的共享库访问RTLD_GLOBAL:加载a.so时,将其符号加入全局符号表,同时允许a.so从已加载的全局符号中解析自身未定义的符号(这里就是b_util)
运行修改后的代码,会输出b_util,实现预期的调用。
内容的提问来源于stack exchange,提问作者MyNameIsTrez
相关产品推荐
相关产品推荐

