Загрузка разделяемой библиотеки по пути во время выполнения
Я строю Java-приложение, которое использует разделяемую библиотеку, написанную на C++ и скомпилированную для разных операционных систем. Проблема в том, что эта общая библиотека сама зависит от дополнительной библиотеки, которую обычно находит в соответствующей переменной среды (PATH
, LIBRARY_PATH
или же LD_LIBRARY_PATH
).
Я могу - но не хочу - устанавливать эти переменные среды. Я бы предпочел загрузить необходимые разделяемые библиотеки по заданному пути во время выполнения - как плагин. И нет - я не хочу никаких стартовых приложений, которые запускают новый процесс в новой среде. Кто-нибудь знает, как этого добиться?
Я знаю, что это должно быть возможно, так как одна из используемых мной библиотек способна загружать свои плагины по заданному пути. Конечно, я бы предпочел независимый от платформы код, но если это невозможно, отдельные решения для Windows, Linux и MacOS также сделали бы это.
РЕДАКТИРОВАТЬ Я должен был упомянуть, что разделяемая библиотека, которую я хотел бы использовать, является объектно-ориентированной, что означает, что привязка отдельных функций этого не сделает.
4 ответа
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) для более подробной информации.
В Windows вы можете использовать LoadLibrary
и в Linux, dlopen
, API чрезвычайно похожи и могут напрямую загружать so/dll, предоставляя полный путь. Это работает, если это зависимость во время выполнения (после загрузки вы "связываете", вызывая GetProcAddress
/dlsym
.)
Я согласен с другими постерами об использовании dlopen и LoadLibrary. Libltdl предоставляет вам независимый от платформы интерфейс для этих функций.
Я не думаю, что вы можете сделать это для этого.
Большинство Dll имеют своего рода функцию init(), которая должна вызываться после загрузки, и иногда функции init() требуются некоторые параметры, и она возвращает некоторый дескриптор, который будет использоваться для вызова функций dll. Знаете ли вы определение дополнительной библиотеки?
Тогда первая библиотека не может просто посмотреть, находится ли DLL X в ОЗУ только по ее имени. Он может находиться в другом каталоге или в другой сборке / версии. ОС распознает библиотеку, если полный путь совпадает с уже загруженной, и предоставит доступ к ней, а не загрузит ее второй раз.
Другая библиотека может загружать свои плагины из другого пути, потому что она написана так, чтобы не зависеть от PATH, и они являются его собственными плагинами.
Вы пытаетесь обновить переменные среды процесса из кода перед загрузкой Dll? Это не зависит от начального процесса.