Загружать общую библиотеку по пути во время выполнения
Я создаю приложение Java, которое использует общую библиотеку, написанную на С++ и скомпилированную для разных операционных систем. Проблема в том, что эта общая библиотека сама зависит от дополнительной библиотеки, которую она обычно находит под соответствующей переменной среды (PATH, LIBRARY_PATH или LD_LIBRARY_PATH).
Я могу - но не хочу - устанавливать эти переменные среды. Я бы предпочел загружать необходимые общие библиотеки из заданного пути во время выполнения - точно так же, как плагин. И нет - я не хочу, чтобы какое-либо стартовое приложение запускало новый процесс с новой средой. Кто-нибудь знает, как достичь этого?
Я знаю, что это должно быть возможно, поскольку одна из библиотек, которые я использую, способна загружать свои плагины из заданного пути. Конечно, я бы предпочел независимый от платформы код, но, если это невозможно, будут также выполняться отдельные решения для Windows, Linux и MacOS.
ИЗМЕНИТЬ
Я должен был упомянуть, что разделяемая библиотека, которую я хотел бы использовать, является объектно-ориентированной, что означает, что привязка отдельных функций не будет делать этого.
Ответы
Ответ 1
Un UNIX/Linux системы вы можете использовать dlopen
. Тогда вы должны получить все символы, которые вам нужны, через dlsym
Простой пример:
typedef int (*some_func)(char *param);
void *myso = dlopen("/path/to/my.so", RTLD_NOW);
some_func *func = dlsym(myso, "function_name_to_fetch");
func("foo");
dlclose(myso);
Загрузите .so и выполните функцию function_name_to_fetch(). Подробнее см. на странице man dlopen (1).
Ответ 2
В Windows вы можете использовать LoadLibrary
и в Linux, dlopen
. API-интерфейсы очень похожи и могут напрямую загрузить dll-dll, предоставив полный путь. Это работает, если это зависимость времени выполнения (после загрузки вы "связываете", вызывая GetProcAddress
/dlsym
.)
Ответ 3
Я согласен с другими плакатами об использовании dlopen и LoadLibrary. libltdl предоставляет вам независимый от платформы интерфейс для этих функций.
Ответ 4
Я не думаю, что вы можете это сделать.
У большинства Dll есть некоторая функция init(), которая должна вызываться после ее загрузки, а когда-то функция init() нуждается в некоторых параметрах и возвращает некоторый дескриптор, который будет использоваться для вызова функций dll. Вы знаете определение дополнительной библиотеки?
Тогда первая библиотека не может просто посмотреть, находится ли DLL X в ОЗУ только с использованием ее имени. Тот, который ему нужен, может быть в другом каталоге или другой сборке/версии. ОС распознает библиотеку, если полный путь будет таким же, как и другой, уже загруженный, и он будет делиться им, а не загружать его второй раз.
Другая библиотека может загружать свои плагины с другого пути, потому что она написана, чтобы не зависеть от PATH, и они являются его собственными плагинами.
Вы пытаетесь обновить переменные среды процесса из кода перед загрузкой Dll? Это не будет зависеть от стартового процесса.