Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C+的最佳实践+;Linux中的插件程序 P>可以有人知道什么是将插件加载到C++ Linux程序中的最佳实践?_C++_Linux_Dlopen_Readelf - Fatal编程技术网

C+的最佳实践+;Linux中的插件程序 P>可以有人知道什么是将插件加载到C++ Linux程序中的最佳实践?

C+的最佳实践+;Linux中的插件程序 P>可以有人知道什么是将插件加载到C++ Linux程序中的最佳实践?,c++,linux,dlopen,readelf,C++,Linux,Dlopen,Readelf,假设我们有一个带有插件(libsyntax.so)的程序(编辑器)。编辑器的配置文件包含libsyntax.so库的路径(plugin1=/opt/editor/gizmos/libsyntax.so)。编辑器读取配置,然后调用: void* library = dlopen(path, RTLD_NOW|RTLD_GLOBAL); MYFUN* function = (MYFUN*)dlsym(library, "function"); 一切正常,一切正常 现在让我们假设(libsyntax

假设我们有一个带有插件(libsyntax.so)的程序(编辑器)。编辑器的配置文件包含libsyntax.so库的路径(plugin1=/opt/editor/gizmos/libsyntax.so)。编辑器读取配置,然后调用:

void* library = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
MYFUN* function = (MYFUN*)dlsym(library, "function");
一切正常,一切正常

现在让我们假设(libsyntax.so)依赖于一个助手库(libcolor.so)。当我们运行readelf时,我们得到:

readelf -d libsyntax.so 

Dynamic section at offset 0x12b6b48 contains 31 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libcolor.so]
 ...
但是,此时上面的dlopen()失败,错误是“没有这样的文件或目录”。使用LD_DEBUG=all表明加载libsyntax.so后,消息如下:

28664:  file=libcolor.so [0];  needed by /home/.../libsyntax.so [0]
28664:  find library=libcolor.so [0]; searching
28664:   search cache=/etc/ld.so.cache
28664:   search path=/lib64/tls/x86_64:/lib64/tls:...:/usr/lib64 (system search path)
28664:    trying file=/lib64/tls/x86_64/libcolor.so
          ... and so on
加载程序/链接器正在标准位置查找,显然,没有找到我的依赖项。这可以通过ldconfig或LD_LIBRARY_PATH轻松解决,但这两种解决方案都感觉脏兮兮


有没有一种干净的方法来加载插件和依赖项?您是如何做到这一点的?

确保找到依赖项的一种干净方法是,在将程序及其插件链接到可以找到依赖项的合理位置的过程中,设置运行时搜索路径()

如果为二进制文件设置了rpath(您可以通过
readelf
看到),则链接器将使用除了默认系统位置之外的其他路径,以及
LD\u LIBRARY\u PATH

此外,还有一个特殊的变量,
$ORIGIN
,它在运行时总是解析为当前二进制文件的位置,您可以设置与此相关的路径

例如,如果应用程序的根路径(包含主可执行文件)是
/opt/editor
,则插件位于
/opt/editor/gizmos
,假设您有另一个文件夹
/opt/editor/lib
,并具有其他依赖项,则可以使用链接器选项:

# editor executable
-Wl,-rpath=$ORIGIN/lib
# plugins
-Wl,-rpath=$ORIGIN/../lib,-rpath=$ORIGIN

从长远来看,我认为图书馆是你的朋友。作为插件接口的定义,只需定义插件所需的库的位置,并确保在程序中将LD_LIBARY_路径设置为该位置


只需在调用dlopen之前设置它,库就可以加载了。程序中不需要其他更改,插件本身也不需要特殊链接。

我希望避免使用RPATH和RUNPATH。无论如何,我认为RPATH应该被弃用,不?IIRC,
$ORIGIN
应该被shell引用。当链接
libsyntax.so
时,使用选项
-Wl,-RPATH,/path1/path2
(libcolor.so实际所在的路径)我做了一些实验,发现如果我的程序有RPATH,它会找到libsyntax,但不会找到libcolor。我必须向libsyntax添加RPATH才能找到libcolor。