有人可以阐明将插件加载到C++ Linux程序的最佳实践是什么吗?

假设我们有一个带有插件(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)。

如果将rpath设置为二进制文件(可以使用readelf看到),则链接器将使用默认系统位置和LD_LIBRARY_PATH之外列出的其他路径。

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

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

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

10-02 06:13
查看更多