改写的问题(尽管已经解决):

我一直在使用dlopen(3)在Linux上加载共享对象库时遇到麻烦。该库是由我构建的库系统的一部分,这些库均在运行时由中央可执行文件加载。所有这些都在Code::Blocks中组织到一个工作区中,每个项目在名为Source的目录中都有自己的文件夹,该目录随程序一起提供。可执行文件的构建目录是从其自身源代码向后的两个目录,以便exectuable和Source文件夹位于同一目录中。这些库也与可执行文件构建在同一目录中,因此我自然地传递了库名我正在尝试如图所示打开:

int main(int argc, char** argv) {
    void* hLibrary = dlopen("libLibrary.so", RTLD_NOW | RTLD_GLOBAL);
    if(hLibrary == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    return 0;
}

当构建目录与源代码相同时,这是可行的,直到我将源代码的目录更改为上述布局。此时的问题是,即使文件明显存在且与可执行文件位于同一目录中,dlerror()也会返回“无法打开libLibrary.so:没有这样的文件或目录”。然后,我尝试传递“/libLibrary.so”,因为根据dlopen(3)的手册页,添加/表示相对目录。这返回了相同的错误。

解决方案是需要一个“./”-“。”。表示可执行文件的工作目录-需要在Code::Blocks中将工作目录更改为要生成可执行文件的位置。以下内容非常适用:
void* hLibrary = dlopen("./libLibrary.so", RTLD_NOW | RTLD_GLOBAL);

这实际上并没有显示完整的解决方案,但是以下内容基本上与我正在做的事情等效:
void* hLibrary = dlopen("./../../libLibrary.so", RTLD_NOW | RTLD_GLOBAL);

希望这可以更好地解释这种情况。

最佳答案

阅读dlopen(3)手册页(例如,通过在计算机上的终端中键入man dlopen):


   o   (ELF only) If the executable file for the calling program
       contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
       then the directories listed in the DT_RPATH tag are searched.

   o   If, at the time that the program was started, the environment
       variable LD_LIBRARY_PATH was defined to contain a colon-separated
       list of directories, then these are searched.  (As a security
       measure this variable is ignored for set-user-ID and set-group-ID
       programs.)

   o   (ELF only) If the executable file for the calling program
       contains a DT_RUNPATH tag, then the directories listed in that
       tag are searched.

   o   The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
       checked to see whether it contains an entry for filename.

   o   The directories /lib and /usr/lib are searched (in that order).

因此,您需要调用dlopen("./libLibraryName.so", RTLD_NOW)-不仅仅是dlopen("libLibraryName.so", RTLD_NOW),它希望您的插件在$LD_LIBRARY_PATH等中位于您的/usr/lib/中... ...-或将.添加到您的LD_LIBRARY_PATH中(出于安全原因,我不建议这样做)。

作为Jhonnash answered,当dlerror(或dlopen)失败时,应使用并显示dlsym的结果:
  void* dlh = dlopen("./libLibraryName.so", RTLD_NOW);
  if (!dlh)
    { fprintf(stderr, "dlopen failed: %s\n", dlerror());
      exit(EXIT_FAILURE); };

您可能需要阅读Advanced Linux Programming之类的书,以大致了解Linux系统编程。

关于C++ Linux : dlopen can't find . so库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17715774/

10-11 22:38