在我的目录里,我有两个文件。一个是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的文档
如果dlopen()因任何原因失败,则返回NULL
那么,当库文件与CPP文件位于同一个目录时,为什么返回NULL呢?
更新:
我现在已经将dlopen()添加到我的CPP文件中,这将输出如下:
bar.so: cannot open shared object file: No such file or directory
但我不明白..。bar.so和foo.cpp位于同一个目录中,可执行文件构建在同一个目录中,在运行可执行文件时我也在同一个目录中。
因此,我尝试为bar.so使用绝对路径,但随后收到了一个新错误:
invalid ELF header
经过一个快速的谷歌,我认为这可能是由于我的Ubuntu安装。我实际上是在使用MacBook,并且已经安装了Ubuntu的本机副本(不是虚拟机)。这似乎是造成问题的原因,但我不知道如何解决。也许这个库文件不会在MacBook Ubuntu上工作。
发布于 2019-06-10 20:22:06
那么,当库文件与CPP文件位于同一个目录时,为什么返回NULL呢?
.cpp文件的位置在这里与此无关。
可执行文件的位置(分别是LD_LIBRRY_PATH的设置)是运行时用来解析的。
无论如何,LD_LIBRRY_PATH不是一个推荐的长期解决方案.简单的方法是使用"./bar.so"而不是"bar.so",以便dlopen()首先在当前目录中查找。但是,当前目录可能与可执行文件存储的目录不一样。在这种情况下,dlopen()仍然会失败。
另一种解决方案是在编译可执行文件时将-Wl,-rpath='$ORIGIN'添加到编译标志中(在本例中为foo.cpp),并像前面那样传递"bar.so"。当使用$ORIGIN作为rpath时,不管当前目录是什么。dlopen()总是首先查找可执行文件的目录。但是请注意,这将导致首先在当前目录中查找所有库,而不仅仅是那些尝试dlopen()的库。可能是你想要的,也可能不是你想要的。
因此,最好的解决方案是在运行时获取可执行文件所在的目录的路径,并将其用作bar.so的路径。这是针对系统的。在Linux上,请参见:Get path of executable
https://stackoverflow.com/questions/56532981
复制相似问题