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的目录中被赋予其自己的文件夹,该目录将随程序一起提供。可执行文件的构建目录是从其自己的源代码向后的两个目录,因此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;
}
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.
希望这能更好地解释情况。
2 个解决方案
#1
11
Read the dlopen(3) man page (e.g. by typing man dlopen
in 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):
如果filename包含斜杠(“/”),则将其解释为(相对或绝对)路径名。否则,动态链接器将按如下方式搜索库(有关详细信息,请参阅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_PATH
on in /usr/lib/
etc .... - or add .
to your LD_LIBRARY_PATH
(which I don't recommend for security reasons).
所以你需要调用dlopen(“./ libLibraryName.so”,RTLD_NOW) - 而不仅仅是dlopen(“libLibraryName.so”,RTLD_NOW),它希望你的插件位于/ usr / lib / etc中的$ LD_LIBRARY_PATH中。 .. - 或添加。到您的LD_LIBRARY_PATH(出于安全原因,我不建议这样做)。
As Jhonnash answered you should use and display the result of dlerror
when dlopen
(or dlsym
) fails:
正如Jhonnash回答的那样,当dlopen(或dlsym)失败时,你应该使用并显示dlerror的结果:
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 Programming to get some knowledge about Linux system programming in general.
您可能希望阅读一些书籍,如高级Linux编程,以获得有关Linux系统编程的一般知识。
#2
#1
11
Read the dlopen(3) man page (e.g. by typing man dlopen
in 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):
如果filename包含斜杠(“/”),则将其解释为(相对或绝对)路径名。否则,动态链接器将按如下方式搜索库(有关详细信息,请参阅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_PATH
on in /usr/lib/
etc .... - or add .
to your LD_LIBRARY_PATH
(which I don't recommend for security reasons).
所以你需要调用dlopen(“./ libLibraryName.so”,RTLD_NOW) - 而不仅仅是dlopen(“libLibraryName.so”,RTLD_NOW),它希望你的插件位于/ usr / lib / etc中的$ LD_LIBRARY_PATH中。 .. - 或添加。到您的LD_LIBRARY_PATH(出于安全原因,我不建议这样做)。
As Jhonnash answered you should use and display the result of dlerror
when dlopen
(or dlsym
) fails:
正如Jhonnash回答的那样,当dlopen(或dlsym)失败时,你应该使用并显示dlerror的结果:
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 Programming to get some knowledge about Linux system programming in general.
您可能希望阅读一些书籍,如高级Linux编程,以获得有关Linux系统编程的一般知识。