Проблема JNI при вызове собственной библиотеки, которая загружает другую собственную библиотеку - PullRequest
2 голосов
/ 07 апреля 2010

У меня странная проблема. У меня есть проект на C ++, который в основном является оберткой для сторонней DLL, например:

MyLibrary
--loads DLL_A
---- загружает DLL_B

Я загружаю DLL_A с помощью LoadLibrary (), оборачиваю несколько ее функций и генерирую свою собственную DLL. Я проверил это в проекте C ++ и C #. Оба делают все, что должны: загружают DLL_A, выполняют пару вызовов функций и косвенно загружают DLL_B. Проблема в том, когда я собираю DLL для Java и делаю звонки через JNI. Все работает так, как должно (без java.lang.UnsatisfiedLinkError), но когда приходит время для DLL_A загрузить DLL_B, это не работает. После отладки загрузка DLL_B происходит при вызове функции в DLL_A, которая принимает обратный вызов. При вызове из Java этот вызов функции кажется неудачным (с указателем функции все в порядке, и фактический вызов происходит без помех), и я получаю странное всплывающее окно, в котором говорится, что DLL_B не удалось загрузить, и моя программа остается в ожидании обратный вызов, который никогда не происходит. Я могу явно загрузить DLL_B просто отлично (как из Java, так и из C ++), и я проверил все возможные пути, переменные пути и попытался поместить dll повсюду, чтобы посмотреть, может ли это выглядеть где-то забавно. Я почти уверен, что это не проблема пути.

В конечном итоге я не знаю, как DLL_A загружает DLL_B, и я не могу понять, почему все отлично работает в C ++ и C #, но не в Java. Я совершенно сбит с толку. Это все еще может быть чем-то конкретным для моей установки (хотя я выглядел так же усердно, как могу), но я выкидываю этот сценарий, чтобы посмотреть, не сталкивался ли кто-нибудь с подобной проблемой.

-Dave

1 Ответ

2 голосов
/ 07 апреля 2010

На самом деле есть только два способа, которыми одна DLL может загрузить другую в Windows - либо они делают это явно, используя LoadLibrary(), либо это неявно, связывая первую DLL с библиотекой импорта второй. Вы должны быть в состоянии использовать Dependency Walker , чтобы узнать, является ли DLL_B зависимой от DLL_A или нет. Запуск depwalker также покажет вам, находится ли DLL_B на пути, если он неявно связан или нет.

Я бы также запустил depwalker на DLL_B, чтобы убедиться, что нет никаких удивительных зависимостей для DLL_B - проблема, которую вы видите, может быть вызвана тем, что DLL_B не может загрузить одну из своих зависимостей, а не DLL_A не может найти DLL_B.

IIRC Windows будет сканировать PATH на наличие неявно связанных библиотек, поэтому проверьте, соответствует ли ваш вызов вашего Java-процесса пути. Документация для LoadLibrary объясняет, как LoadLibrary сканирует DLL.

Вы сказали, что вам удалось загрузить DLL_B непосредственно из Java; Когда вы делаете это и затем вызываете через DLL_A, механизм обратного вызова начинает работать? Это может быть несколько уродливым временным решением.

...