Повторное использование разделяемой библиотеки рук

У меня уже есть отдельная библиотека андроидов (libtest.so). Я заинтересован в повторном использовании одной функции (у которой не так много зависимостей – она ​​просто создает экземпляр класса и вызывает два метода). Я хотел бы вызвать эту функцию (она принимает один аргумент std :: string) и получить возвращаемое значение.

Можно ли это сделать? У меня нет файлов заголовков.

Я пробовал этот Android.mk, я поставил libtest.so в /jni и /libs/armeabi , /lib/armeabi . На данный момент мой файл cpp компилируется, но что теперь? Если это возможно, как я могу вызвать функцию из libtest.so? Я знаю его имя от objdump

  LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= libtest LOCAL_SRC_FILES := libtest.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.cpp LOCAL_SHARED_LIBRARIES := libtest include $(BUILD_SHARED_LIBRARY) 

Редактировать:

Я попытался добавить библиотеку prebuild из образца hello-jni с этим android.mk:

 include $(CLEAR_VARS) LOCAL_MODULE:= libhello-jni LOCAL_SRC_FILES := libhello-jni.so include $(PREBUILT_SHARED_LIBRARY) 

И это сработало, но тот же код для libtest.so показывает следующую ошибку (при запуске)

 UnsatisfiedLinkError: Cannot load libtest.so: FindLibrary returned null 

Libtest.so присутствует в папке (на устройстве в /data/data/[package]/lib ) рядом с libhello-jni.so. Что может быть неправильным?

У меня есть приложение, в котором я делаю что-то похожее на то, что вам нужно (или, может быть, именно то, что вам нужно).

  1. У меня есть предварительно скомпилированные библиотеки в виде файлов * .so. (Например, lib1.so, lib2.so и т. Д.), Которые поставляются с некоторыми заголовками.

  2. Я создал модуль, который использует предварительно скомпилированные библиотеки, включая их заголовки и файлы * .so. В примере я назвал его «libtestwrapper». Модуль определяет собственные исходные файлы и, возможно, включает в себя. Функциональность модуля может быть экспортирована для второго модуля (если вы предоставляете файлы заголовков), как описано ниже.

  3. Я создал второй модуль (newModule), который использует первый (libtestwrapper), добавив его в «LOCAL_SHARED_LIBRARIES». Это делает ваши ранее экспортированные файлы заголовков (в 'libtestwrapper') доступными для 'newModule'.

Вот содержание моего Android.mk:

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libtestwrapper LOCAL_SRC_FILES := libtestUsage.c # Use the methods of libtest.h here LOCAL_C_INCLUDES := $(LOCAL_PATH)/include # This is where libtest.h should be # provide this line if you intend to export any header files to another module #LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/include # you may also use a different directory than 'include' LOCAL_LDLIBS := -L$(LOCAL_PATH)/dir_with_libtest_so -libtest # -llog etc. #optionally add any as needed: -llog -ljnigraphics -lz -ldl -lgcc # '-libtest' corresponds to 'libtest.so' - the names must match # -llog is for logcat for example include $(BUILD_SHARED_LIBRARY) # Optional: # Define a second module wich is making use of the first one (ie libtestwrapper) include $(CLEAR_VARS) LOCAL_MODULE := newModule # this module will be making use of the first one (if needed) # Add local source files. If the files are stored in directories # you have to provide a relative path starting inside the 'jni' directory. # The example is for this structure: jni/dirToSourceFiles1/*.cpp LOCAL_SRC_FILES := dirToSourceFiles1/SourceFile1.cpp dirToSourceFiles1/SourceFile2.cpp LOCAL_C_INCLUDES += $(LOCAL_PATH)/newModule_include # path where the headers of this module are stored LOCAL_SHARED_LIBRARIES += libtestwrapper # make use of the previous module # Optionally add this line if any other libs should be used #LOCAL_LDLIBS := -llog -ljnigraphics -lz -ldl -lgcc include $(BUILD_SHARED_LIBRARY) 

Если библиотека не была построена с помощью инструментов сборки Android (например, NDK), то у нее, вероятно, не будет совместимого ABI. Даже если он был построен с использованием ARMv5 EABI-совместимой версии gcc, если это зависит от любого libc / libc ++, тогда он будет терпеть неудачу. Библиотека bionic C не является бинарной совместимой с другими библиотеками C / C ++, и вы должны создать на ней собственный код, даже для общей библиотеки.

Если вы хотите вызвать метод C ++ из Java и вам необходимо передать такие типы, как string, вы должны написать уровень конверсии с использованием JNI (Java Native interface).

Вы можете найти несколько руководств о том, как это делается в Интернете. Пример здесь

Как резюме

1- Объявить собственный метод в Java

2- Создайте подпись, которая должна быть экспортирована из вашей библиотеки c ++, которая будет вызываться, когда этот метод вызывается в Java.

Пример команды: javah com.companyname.JavaTestCaller

Эта команда будет генерировать файл заголовка с соответствующей сигнатурой.

3- Подготовьте библиотеку c ++, которая содержит этот метод. Выполняйте все, что захотите, в этом методе (вызовите libtest.so, если хотите) и верните результат. Используйте методы, когда необходимы преобразования типов.

4- Поместите эту новую библиотеку рядом с вашим libtest.so в ваше приложение. Загрузите эту библиотеку после libtest.so.

5. Вызовите собственный метод Java из приложения.

Вы пытались изменить эту строку:

 LOCAL_SHARED_LIBRARIES := libtest 

чтобы:

 LOCAL_SHARED_LIBRARIES := test 

Lib и .so автоматически используются для разрешения имени разделяемой библиотеки. Вы также можете использовать:

 LOCAL_LDLIBS += -ltest 

Еще одна опция – PREBUILT_SHARED_LIBRARY.

Поскольку у вас нет файла заголовка, вам может потребоваться написать разделяемую библиотеку, которую вы используете для вызова предварительно созданной библиотеки. Ваше приложение будет вызывать новую общую библиотеку, которая экспортирует правильные имена JNI-символов, а новая общая библиотека вызовет функцию md5 ().