4

这是设置:

  1. A有一个加载的应用程序liba.so(在编译时链接)
  2. liba.so导出符号expA
  3. 我既不控制A也不liba.so
  4. 应用程序 A 可以通过(想想插件架构)将我指定的库加载libmine.so到同一进程中dlopen
  5. 我需要使用expAfromlibmine.so但不知道如何在没有明确链接到的情况下找到它liba.so,这是我迄今为止一直在做的事情。我认为这在现实世界中行不通,因为不能保证该符号与我的本地副本中的地址相同liba.so(或者是吗?)。libmine.so将是封闭源代码,不能用A.

我从来没有做过这样的事情,所以对库加载的细节有点不清楚。例如,如果我尝试dlopen("liba.so")from inside libmine.so,我会得到一个已加载库的句柄还是一个新副本?

就如何libmine.so加载而言,我所知道的是它将被加载RTLD_LAZY(仅此而已)。

任何帮助和指点将不胜感激!

4

1 回答 1

4

如果所有liba.so库都dlopen使用 编辑RTLD_GLOBAL,那么您可以使用dlsym(RTLD_DEFAULT, "expA")来查找符号,而无需重新打开库。

如果该liba.so库是dlopened using ,RTLD_LOCAL那么您将需要dlopen在您自己的libmine.so. 请注意以下事项:

如果使用 dlopen() 再次加载相同的库,则返回相同的文件句柄。dl 库维护库句柄的引用计数,因此在 dlclose() 调用它的次数与 dlopen() 成功的次数相同之前,不会释放动态库。_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;
    }
}

那是伪代码,几乎没有错误处理。

于 2013-09-15T11:09:01.283 回答