Переопределение @executable_path в DLL, загруженной с помощью dlopen()

Операционная система - MacOS X, в частности 10.5 (Leopard) на PowerPC G4, но у меня та же проблема на x86 под управлением 10.6.

Я пишу приложение, которое динамически загружает DLL. DLL (назовем это foo.dylib) является частью другого приложения, расположенного в другом месте на жестком диске; мое приложение находит foo.dylib программно (точное расположение может измениться, возможно, пользователь определяет путь к DLL через графический интерфейс непосредственно из запущенного приложения). Например, предположим, что мое приложение находится в каталоге /Application/MyApp.app/Contents/MacOS, а также foo.dylib случается в /Application/OtherApp.app/Contents/MacOS, Загрузка DLL использует dlopen(),

Теперь получается, что foo.dylib сама по себе нужна куча других DLL, которые находятся в том же каталоге, но о которых я ничего не знаю заранее. Каждая такая дополнительная DLL зарегистрирована в foo.dylib с таким путем, как @executable_path/bar.dylib, Семантика @executable_path в том, что он должен быть заменен каталогом, в котором был найден текущий исполняемый файл процесса. Это прекрасно работает для OtherApp, а не для меня: когда я открываю foo.dylib, он пытается загрузить bar.dylibи ищет это в /Application/MyApp.app/Contents/MacOS/bar.dylib, который не является правильным каталогом.

Обходной путь должен установить DYLD_FALLBACK_LIBRARY_PATH переменная среды для /Application/OtherApp.app/Contents/MacOS, но это нужно сделать перед запуском моего приложения (эта переменная среды читается динамическим компоновщиком только один раз; программно изменяя ее значение с помощью setenv() или же putenv() не имеет никакого эффекта). Это несовместимо с динамическим обнаружением местоположения foo.dylib файл.

Есть ли программный способ переопределить эффект @executable_path?

2 ответа

Решение

Читая исходный код dyld (ищите @executable_path), я бы сказал, что ответ однозначно "нет". @executable_path заменяется на основной путь к исполняемому файлу, который хранится в виде глобальной строки в модуле dyld.

И да, ваше подозрение верное, dyld читает и сохраняет переменные окружения при запуске, поэтому вы не можете изменять их на лету (вы можете искать тот же исходный файл, который я связал для DYLD_LIBRARY_PATH). Вы могли бы иметь приложение-заглушку, которое устанавливает переменные среды и затем запускает ваше реальное приложение. Здесь Dyld не предлагает вам много решений, он не предназначен для того, чтобы позволить вам ссылаться в произвольных частных сторонних библиотеках.

Если вы поддерживаете OtherApp, вы можете использовать @loader_path вместо @executable_path для определения местоположения зависимостей: @loader_path всегда разрешает путь к модулю (то есть библиотеке или исполняемому файлу), который требует загрузки библиотеки, поэтому рекурсивные зависимости всегда найдены.

Это доступно с Mac Os 10.5 и далее.
Смотрите "man dyld" для подробной информации.

Другой вариант будет dlopenЗависимости перед основной библиотекой.

Другие вопросы по тегам