3

有人可以阐明将插件加载到 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 轻松解决,但两种解决方案都感觉很脏。

有没有一种干净的方式来加载插件和依赖项?你是怎么做到的?

4

2 回答 2

1

确保找到依赖项的一种干净方法是在将程序及其插件链接到可以找到依赖项的合理位置期间设置运行时搜索路径( 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
于 2016-07-07T21:20:58.047 回答
0

Persinally,我认为 LD_LIBARY_PATH 是你的朋友。只需定义插件接口的定义,插件需要的库应该位于何处,并确保在您的程序中将 LD_LIBARY_PATH 设置为该位置。

在调用 dlopen 之前简单地设置它应该足以加载库。程序中不需要其他更改,也不需要插件本身的特殊链接。

于 2016-07-09T13:57:19.940 回答