#android #android_ndk #build
Есть библиотека, назовем ее Library.so и инклуды к ней. Без jni. Нужно присоединить
ее к проекту. Для этого пишу jni обертку.
Собираю все следующим образом (Android.mk):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Library
LOCAL_SRC_FILES := Library.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Library_jni
LOCAL_SRC_FILES := Library_jni.c
LOCAL_LDLIBS += $(LOCAL_PATH)/../libs/armeabi/libLibrary.so
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
Все собирается нормально, но при выполнении:
static
{
try{
System.loadLibrary("Library_jni");
}catch(UnsatisfiedLinkError use){
Log.e("JNI","ERROR: Could not load Library_jni.so");
}
}
сообщение об ошибке выводится. Если не отлавливать, вылетает с исключением:
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]:
69 could not load needed library 'libLibrary.so' for 'libLibrary_jni.so' (load_library[1091]:
Library 'libLibrary.so' not found)
То есть библиотека-обертка не может загрузиться, потому что на найдена основная библиотека.
Как я понимаю, она ищется по адресу: $(LOCAL_PATH)/../libs/armeabi/libLibrary.so, но
на устройстве, само собой такой папки нет. На устройстве библиотеки лежат в data/data/my.package/lib.
Понятно, что она и не найдется.
Но при любом другом адресе в LOCAL_LDLIBS линковщик не может найти нужный файл, сборка
завершается с ошибкой. Если писать только
LOCAL_SHARE_LIBRARIES := libLibrary
линковщик не видит реализаций функций из внутренней библиотеки, заголовки видит нормально.
Как правильно сослаться на динамическую библиотеку из другой динамической библиотеки,
чтобы и на этапе сборки и на этапе выполнения не было ошибок? Можно сделать так, чтобы
при сборке библиотека искалась по одному адресу, а при выполнении по другому?
Ответы
Ответ 1
Проблема в том, что загрузчик Андроида автоматически не подгружает зависимости. То есть если библиотека А зависит от библиотеки Б, то пользователь должен самостоятельно грузить библиотеку Б до библиотеки А. Вы можете обойти ограничение, если либо внедрите JNI в основную библиотеку, либо загрузите вручную (dlopen, dlclose) основную библиотеку из вспомогательной.Ответ 2
Все оказалось просто, нужно подгружать библиотеки так: static { try{ System.loadLibrary("Library"); System.loadLibrary("Library_jni"); }catch(UnsatisfiedLinkError use){ use.printStackTrace(); } } Тогда все работает.
Комментариев нет:
Отправить комментарий