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