问题是我dlopen
用来加载一个库(.so 是我写的,它不是系统库),但是我得到了标题中显示的错误。
- 我已经包括
dlfcn.h
- 在编译器中,我使用了
-ldl
命令 - 我要加载的只是源代码文件夹,我尝试添加
-L.
,但它不起作用。
问题是我dlopen
用来加载一个库(.so 是我写的,它不是系统库),但是我得到了标题中显示的错误。
dlfcn.h
-ldl
命令-L.
,但它不起作用。如果您要 dlopen 的库不在标准搜索路径中,您有多种选择:
在 dlopen 中指定文件的完整路径
dlopen("/full/path/to/libfile.so");
通过 LD_LIBRARY_PATH 添加库的路径
LD_LIBRARY_PATH=/path/to/library/ ./executable
使用 ld -rpath 选项将库路径添加到应用程序。
g++ -link stuff- -Wl,-rpath=/path/to/library/
请注意,选项 1 和 3 将库路径硬编码到您的应用程序中。-rpath 确实有一个选项来指定相对路径,即
-Wl,-rpath=$ORIGIN/../lib/
将相对路径嵌入到应用程序中。
找出代码出错的最残酷和有效的方法是以下命令,它将激活共享库的调试模式,并在此处记录:
export LD_DEBUG=libs
然后,您会惊讶地弹出这么多信息。不用担心,这些信息会告诉您刚刚键入的命令需要哪些共享库以及在哪里可以找到这些所需的库。例如,如果您键入,屏幕将被重置,然后将打印reset
有关共享库命令需要的信息。reset
然后,执行你的“有问题的”可执行文件,看看出了什么问题。
PS.1:根据您接受的神话解决方案:
在 dlopen 中指定文件的完整路径
dlopen("/full/path/to/libfile.so");
似乎即使您在dlopen
函数中使用绝对或相对路径,找不到目录的错误仍然会出现。我正在使用 CentOS,我的 Debian 也有这个问题。所以我认为神话提供的第一个解决方案是错误的。您可以在我上面提到的“调试”模式下进行验证。
PS.2:如果您“安装”或“编译”共享库而不是通过包管理器安装它,则必须运行sudo ldconfig /path/where/not/found/shared/library/reside
以通知系统新添加的共享库。例如 :
cp /etc/ld.so.cache ~/ld.so.cache.backup
#cp -r /etc/ld.so.conf.d ~/ld.so.conf.d.backup #sometimes this backup is unnecessary.
#cp /etc/ld.so.conf ~/ld.so.conf.backup #sometimes this backup is unnecessary.
sudo ldconfig /PATH/WHERE/NOT/FOUND/SHARED/LIBRARY/RESIDE
###I am omitting the cp commands to roll back.
###For example, sudo cp -f ld.so.cache /etc/ld.so.cache
要了解这里发生了什么,请仔细阅读上面链接中的所有内容。
PS.3:您始终可以使用命令export LD_DEBUG=help
,export LD_DEBUG=libs
找出-rpath
或LD_LIBRARY_PATH
解决您的问题。你会喜欢这种调试模式。
PS.4:找出问题所在的不那么残酷的方法:
ldd ./YOURproblematicEXECUTABLE
该命令可以告诉您要打开的共享库是否位于。此外,有很多方法可以解决您的问题,每种方法都有其局限性和适用性。所以我强烈建议你阅读我上面提供给你的链接,并了解如何选择解决问题的方法。看完之后,如果你真的觉得自己很“OK”,你还可以阅读这篇更好地理解 Linux 二级依赖关系的例子,以加深理解。
dlopen 的声明看起来像, void *dlopen(const char *filename, int flag);
如果将 para 'filename' 设置为共享库的 name ,则应将当前路径添加到 'LD_LIBRARY_PATH' 中。例如,
1、dlopen("libtest.so" , RTLD_LAZY)
2、在shell中,导出LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
就我而言,解决方案非常简单:
除非明确指定为相对路径,否则路径应为绝对路径
所以我换了
dlopen("mylib.so", RTLD_NOW)
和
dlopen("./mylib.so", RTLD_NOW)
问题解决了。
我会推荐dlerror来了解原因
void* handle = dlopen(SO_FILE, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
if(handle == NULL)
{
printf(LOG_ERROR, "Error: %s\n", dlerror());
assert(0);
}
这将报告错误的详细原因