Лучшие практики для программ на C ++ с плагинами в Linux

Может кто-нибудь пролить свет на то, что лучше всего загружать плагины в программу на 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, но оба решения кажутся грязными.

Есть ли чистый способ загрузить как плагин, так и зависимости? Как ты это делаешь?

3

Решение

Простой способ убедиться, что зависимости найдены, это установить путь поиска во время выполнения (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
1

Другие решения

В общем, я думаю, что LD_LIBARY_PATH ваш друг здесь. Просто определите, как определение для интерфейса плагина, где должны находиться библиотеки, в которых нуждается плагин, и убедитесь, что в вашей программе установлено LD_LIBARY_PATH в этом месте.

Простая установка перед вызовом dlopen должна быть достаточной для загрузки библиотеки. Никаких других изменений в программе не требуется, и никаких специальных ссылок на сам плагин.

0

По вопросам рекламы [email protected]