java.lang.UnsatisfiedLinkError: ошибка dlopen: библиотека не найдена - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь собрать свой Android (нативный) проект с помощью cmake (перенести его из экспериментального плагина gradle, где он использовался для сборки и запуска).

У меня есть некоторый нативный код (назовем его 'a'), который использует другой внешний встроенный библиотечный код (назову его 'b'), и я связал их так: (согласно https://developer.android.com/studio/projects/configure-cmake)

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -frtti -fno-common -fexceptions")

include_directories(
#a's include files' paths
#b's include files' paths)

file(GLOB_RECURSE A_SOURCES
#a's source files' paths)

add_library(a_lib SHARED ${A_SOURCES})
add_library(b_lib SHARED IMPORTED)
set_target_properties(b_lib PROPERTIES IMPORTED_LOCATION "b's .so path")
target_link_libraries(a_lib b_lib)

Я прошел все этапы компиляции и компоновки, и Android Studio приступает к установке APK на моем устройстве. Тем не менее, после запуска приложение зависает со следующим в logcat:

E/ExceptionHandler: Uncaught Exception java.lang.UnsatisfiedLinkError: dlopen failed: library "libb_lib.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:989)
at java.lang.System.loadLibrary(System.java:1530)
at com.mm.projectname.model.libloadingclassname.<clinit>(libloadingclassname.java:99)

Я знаю, что это происходит из-за того, что b_lib .so нет в apk. И я могу видеть символы b вместе с символами a в общей библиотеке a.

Итак, мой вопрос, как я могу

  1. либо упакуйте мои готовые b .so в apk
  2. или запретить системе искать b.so в папке libs и заставить ее искать символы b только в .so.

Я много искал похожие посты и вопросы (например, one и two ), но я не могу заставить что-либо работать. Я действительно ищу правильный способ сделать это - который не будет создавать проблемы в будущем (например, изменение targetSDKversion). Я также попытался собрать готовую библиотеку с последней версией ndk.

Вполне возможно, что я делаю очень маленькую ошибку, и был бы очень признателен, если бы кто-то мог указать на это.

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 21 января 2019
  1. Создайте папку jniLibs в каталоге приложения.
  2. Создайте еще одну папку с именем в соответствии с архитектурой.
  3. Сохраните файл .so в этой папке.
0 голосов
/ 26 сентября 2018

Немного поздно, но кому-то еще может быть интересно (или даже оп).

У меня была та же ситуация, что и в операторе, и я пробовал много разных вещей. Одним из них было попытаться скомпилировать проект с более ранней версией NDK (я думаю, что r14b, но я не совсем уверен). Я получил другую ошибку и сумел отследить проблему, которая хорошо описана здесь , в разделах «Недопустимые записи DT_NEEDED» и «Отсутствует SONAME». Кроме того, проблема описана в этом конкретном вопросе и получила адекватный ответ.

Если вы не можете перекомпилировать разделяемую библиотеку, которую используете, чтобы включить SONAME, как в моем случае, вы можете сделать следующее, что я сделал и смог работать:

  • Включите библиотеку в папку jniLibs в дереве проекта, чтобы она была упакована в ваш APK, но не связывайтесь с ней.
  • Отслеживайте символы функций, которые вы хотите включить, используя любой метод, описанный здесь .
  • Создание указателей функций соответствующих функций в вашем коде C ++.
  • Загрузка общей библиотеки во время выполнения и сопоставление с этими функциями.

Пример кода

Заголовок

private:

typedef uint32_t (*InitX_t)();
typedef uint32_t (*DoX_t)();
typedef uint32_t (*GetX)(uint32_t, char*);

InitX_t InitX;
DoX_t DoX;
GetX_t GetX;

CPP

void *handle = dlopen("libMyLib.so", RTLD_NOW);

if(handle == nullptr)
{
    __android_log_print(ANDROID_LOG_INFO, "My Class", "Could not load library");
}
else
{
    __android_log_print(ANDROID_LOG_INFO, "My Class", "Library loaded");
}

InitX = (InitX_t)dlsym(handle, "InitX_SYMBOL");
ScanX = (ScanX_t)dlsym(handle, "ScanX_SYMBOL");
GetX = (GetX_t)dlsym(handle, "GetX_SYMBOL");

if(ScanX == nullptr || GetX == nullptr || InitX == nullptr)
{
    __android_log_print(ANDROID_LOG_INFO, "My Class", "Could not load functions.");
}

Если все сделано правильно, теперь вы сможете использовать функции как обычно. Однако я понимаю, что это не самый простой процесс, если вы новичок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...