Может кто-нибудь пролить свет на то, что лучше всего загружать плагины в программу на 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
В общем, я думаю, что LD_LIBARY_PATH ваш друг здесь. Просто определите, как определение для интерфейса плагина, где должны находиться библиотеки, в которых нуждается плагин, и убедитесь, что в вашей программе установлено LD_LIBARY_PATH в этом месте.
Простая установка перед вызовом dlopen должна быть достаточной для загрузки библиотеки. Никаких других изменений в программе не требуется, и никаких специальных ссылок на сам плагин.