Страницы

Поиск по вопросам

понедельник, 13 апреля 2020 г.

Android.mk: как правильно присоединить динамическую библиотеку?

#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(); } } Тогда все работает.

Комментариев нет:

Отправить комментарий