我正在编写一些使用动态共享库作为插件的代码。
用于构建共享库的命令行如下所示:
cc -shared -fPIC -o module.so -g -Wall module.c
在模块中,我可以调用已在主可执行文件中加载的任何其他共享库中的函数。
但是我无法访问可执行文件中的(导出的)函数(我得到undefined symbol
错误)。
我对dlopen
的呼吁如下:
void *handle = dlopen(plugin, RTLD_NOW);
任何人都可以建议我的模块如何回调我的可执行文件,而不必将所有可执行文件的实用程序函数放入另一个共享库中?
答案 0 :(得分:30)
正确的解决方案是将-rdynamic
添加到主可执行文件的链接命令中。这会为ld
添加适当的选项(使用GNU ld
时恰好是--export-dynamic
)。
直接添加--export-dynamic
在技术上是不正确的:它是一个链接器选项,因此应添加为-Wl,--export-dynamic
或-Wl,-E
。这也比-rdynamic
更不便携(其他链接器具有等效的,但选项本身也不同)。
答案 1 :(得分:5)
我自己找到了答案。
我必须将--export-dynamic
标志添加到主可执行文件的链接选项中。
创建动态链接时 可执行文件,将所有符号添加到 动态符号表。动态 符号表是符号集 从动态对象可见 在运行时。
如果您不使用此选项,则 动态符号表通常会 仅包含那些符号 由一些动态对象引用 在链接中提到。
如果使用“dlopen”加载动态 需要参考的对象 程序定义的符号, 而不是一些其他动态对象, 那么你可能需要使用 链接程序时的此选项 本身。
答案 2 :(得分:4)
当我遇到同样的问题时,我只使用了以下解决方案。在加载任何插件之前,只需加载程序本身,将其符号带到动态表:
dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);
我认为解决方案更好。原因是,如果你
,它也解决了同样的问题a)您的程序(或三方模块)与共享库链接(不在运行时),这些符号需要在动态表中;
b)无法使用-rdynamic标志重新编译该模块。