c++ - dlopen() 返回 0

标签 c++ linux g++ dlopen

<分区>

在我的目录中,我有两个文件。一个是foo.cpp,另一个是bar.so。在 foo.cpp 中,我尝试加载库 bar.so:

#include <dlfcn.h>
#include <iostream>

int main()
{
    void* handle = dlopen("bar.so", RTLD_NOW | RTLD_GLOBAL);
    std::cout << handle << std::endl;
    return 0;
}

在同一目录中,然后我从命令行编译代码:

g++ foo.cpp -ldl -o test

然而,当执行 test 时,这会打印出 0,并且根据 dlopen 的文档:

If dlopen() fails for any reason, it returns NULL

那么当库文件与 CPP 文件位于同一目录时,为什么返回 NULL?


更新:

我现在已将 dlopen() 添加到我的 CPP 文件中,此输出:

bar.so: 无法打开共享对象文件:没有那个文件或目录

但是我不明白... bar.sofoo.cpp 在同一目录下,可执行文件是在同一目录下构建的,我当我运行可执行文件时,我在同一个目录中。

然后,我尝试为 bar.so 使用绝对路径,但随后收到一个新错误:

无效的 ELF header

快速谷歌后,我认为这可能是由于我安装了 Ubuntu。我实际上使用的是 MacBook,并安装了 Ubuntu 的 native 拷贝(不是虚拟机)。看来这是导致问题的原因,但我不知道如何解决。也许这个库文件将无法在 MacBook Ubuntu 上运行。

最佳答案

So why is this returning NULL, when the library file is in the same directory as the CPP file?

.cpp 文件的位置与此处无关。

可执行文件的位置,分别为LD_LIBRRY_PATH的设置是用来在运行时解析的内容。

无论如何,LD_LIBRRY_PATH 不是推荐的长期解决方案。一个简单的方法是使用 "./bar.so" 而不是 "bar.so" 以便 dlopen() 查找当前目录第一。但是当前目录可能与可执行文件存储的目录不同。在这种情况下,dlopen() 仍然会失败。

另一种解决方案是在编译可执行文件(在本例中为 foo.cpp)时将 -Wl,-rpath='$ORIGIN' 添加到编译标志中,然后像你已经做的那样传递 "bar.so"。当使用 $ORIGIN 作为 rpath 时,当前目录是什么并不重要。 dlopen() 将始终首先查找可执行文件的目录。但请注意,这将导致首先在当前目录中查找所有库,而不仅仅是那些您尝试 dlopen() 的库。它可能是也可能不是您想要的。

所以最好的解决方案是在运行时获取可执行文件所在目录的路径,并将其用作 bar.so 的路径。这是系统特定的。在 Linux 上,请参阅:Get path of executable

关于c++ - dlopen() 返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56532981/

相关文章:

c++ - Websocket 广播不工作

linux - 需要帮助在 korn shell 中创建别名

c++ - 尝试在 Linux 上运行 OpenGL,拥有必要的库但无法运行? (C++)

c++ - Linux 环境中用于 Perl 和 C++ 脚本的最佳且有用的调试工具是什么?

c++ - 如何使用 -std=c++17(可选、任意、string_view、变体)在 g++ 6.2.0 中包含 C++ 17 header

c++ - g++ 签名/符号 : no difference between static and non-static member function?

c++ - g++内部编译器错误段错误与递归constexpr

c++ - Gtkmm-3.0 编译代码抛出 Gtk+2 符号错误

c++ - 是否可以在 cpp 中检查负 0?

c++ - 如何比较函数对象