C++ linux:dlopen 找不到 .so 库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17715774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:18:06  来源:igfitidea点击:

C++ linux: dlopen can't find .so library

c++linuxcodeblocksdynamic-library

提问by NmdMystery

Reworded Question (although it's been solved already):

改写问题(虽然已经解决了):

I've been having trouble using dlopen(3) to load a shared object library on linux. The library is part of a system of libraries built by me that are all loaded at runtime by a central executable. All of this is organized into a single workspace in Code::Blocks, where each project is given its own folder within a directory called Source, which is to be shipped with the program. The build directory of the executable is two directories backward from its own source code so that the exectuable and the Source folder are in the same directory, The libraries also build to the same directory as the executable, so naturally I pass the name of the library I'm trying to open as shown:

我一直在使用 dlopen(3) 在 linux 上加载共享对象库时遇到问题。该库是我构建的库系统的一部分,所有库都在运行时由中央可执行文件加载。所有这些都组织到 Code::Blocks 中的单个工作区中,其中每个项目在名为 Source 的目录中都有自己的文件夹,该文件夹将随程序一起提供。可执行文件的build目录是从它自己的源代码往后两个目录,这样exectuable和Source文件夹在同一个目录下,libraries也和可执行文件build在同一个目录下,所以自然而然我传递了库的名字我试图打开如图所示:

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;
}

This was working at one point when the build directory was the same as the source code, until I changed the directories of the source code around to the arrangement described above. The problem at this point is that dlerror() returns "Cannot open libLibrary.so: no such file or directory," even though the file clearly exists and is in the same directory as the executable. I then tried passing in "/libLibrary.so" instead, because according to the man page on dlopen(3), adding a / indicates a relative directory. This returned the same error.

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

The solution to this was that a "./" was needed - where "." represents the working directory of the executable - and the working directory needed to be changed in Code::Blocks to where the executable was to be built. The following works perfectly:

对此的解决方案是需要一个“./”——其中“.” 代表可执行文件的工作目录 - 以及需要在 Code::Blocks 中将工作目录更改为要构建可执行文件的位置。以下工作完美:

void* hLibrary = dlopen("./libLibrary.so", RTLD_NOW | RTLD_GLOBAL);

This doesn't really show the full solution, but the following is basically the equivalent of what I'm doing:

这并没有真正显示完整的解决方案,但以下内容基本上与我正在做的事情相同:

void* hLibrary = dlopen("./../../libLibrary.so", RTLD_NOW | RTLD_GLOBAL);

Hopefully this explains the situation a little better.

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

采纳答案by Basile Starynkevitch

Read the dlopen(3)man page (e.g. by typing man dlopenin a terminal on your machine):

阅读dlopen(3)手册页(例如通过man dlopen在您的机器上的终端中输入):

If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details):

如果文件名包含斜杠(“/”),则将其解释为(相对或绝对)路径名。否则,动态链接器按如下方式搜索库(有关详细信息,请参见 ld.so(8)):

   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).

So you need to call dlopen("./libLibraryName.so", RTLD_NOW)-not just dlopen("libLibraryName.so", RTLD_NOW)which wants your plugin to be in your $LD_LIBRARY_PATHon in /usr/lib/etc .... - or add .to your LD_LIBRARY_PATH(which I don't recommend for security reasons).

所以你需要调用dlopen("./libLibraryName.so", RTLD_NOW)-not just dlopen("libLibraryName.so", RTLD_NOW)which 希望你的插件在你$LD_LIBRARY_PATH/usr/lib/等等中...... - 或者添加.到你的LD_LIBRARY_PATH(出于安全原因我不建议这样做)。

As Jhonnash answeredyou should use and display the result of dlerrorwhen dlopen(or dlsym) fails:

正如Jhonnash 回答的那样,您应该使用并显示dlerrorwhen dlopen(or dlsym) 失败的结果:

  void* dlh = dlopen("./libLibraryName.so", RTLD_NOW);
  if (!dlh) 
    { fprintf(stderr, "dlopen failed: %s\n", dlerror()); 
      exit(EXIT_FAILURE); };

You might want to read some books like Advanced Linux Programmingto get some knowledge about Linux system programming in general.

您可能想阅读一些诸如Advanced Linux Programming 之类的书籍,以了解有关 Linux 系统编程的一般知识。

回答by suneet saini

About the dlopenis defined; Dynamic library dlopen error can be checked.Undefined symbol errorby this link.

关于dlopen的定义;可以检查动态库 dlopen 错误链接未定义符号错误