以下是设置:
A
加载liba.so
(在编译时链接)liba.so
导出符号expA
A
或liba.so
libmine.so
将我指定的库dlopen
加载到同一进程中(想想插件架构)expA
中的libmine.so
但不知道如何在没有明确链接liba.so
的情况下找到它,这是我到目前为止所做的。我认为这在现实世界中不起作用,因为该符号不能保证与我liba.so
本地副本中的符号相同(或者是它?)。 libmine.so
将是封闭源代码,无法使用A
重新编译。我从未做过这样的事情,所以对库加载的细节有点不清楚。例如,如果我在dlopen("liba.so")
内尝试libmine.so
,我是否会获得已加载的库或新副本的句柄?
就libmine.so
的加载方式而言,我所知道的是它将加载RTLD_LAZY
(并没有其他内容)。
非常感谢任何帮助和指示!
答案 0 :(得分:3)
如果所有liba.so
库都使用dlopen
RTLD_GLOBAL
编辑,那么您可以使用dlsym(RTLD_DEFAULT, "expA")
查找该符号,而无需重新打开该库。
如果liba.so
库dlopen
使用RTLD_LOCAL
,那么您需要在自己dlopen
内再次使用libmine.so
来获取库的句柄。请注意以下事项:
如果使用dlopen()再次加载相同的库,则返回相同的文件句柄。 dl库维护库句柄的引用计数,因此在dlpen()成功调用dlclose()之前,不会释放动态库。 _init()例程(如果存在)仅被调用一次。但随后使用RTLD_NOW进行的调用可能会强制对早先使用RTLD_LAZY加载的库进行符号解析。
即。它与图书馆的副本相同。
机制是(伪),假设expA是一个函数:int expA(int value)
:
int (*fpointer)(int) = NULL;
void *handle = dlopen("liba.so", RTLD_LAZY | RTLD_LOCAL);
if (handle != NULL) {
void *symbol = dlsym(handle, "expA");
if (symbol != NULL) {
fpointer = (int (*)(int ))symbol;
}
}
这是伪代码,几乎没有错误处理。