Android NDK C++ JNI (реализация не найдена для нативных...)
Я пытаюсь использовать NDK с C++ и, похоже, не могу получить правильное соглашение о присвоении имен методам. мой родной метод заключается в следующем:
extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
//
}
}
с заголовком, завернутым в extern "C" {} также.
Все прекрасно компилируется, создает файл.so и копирует в папку libs в моем проекте, но когда я отлаживаю и запускаю в Eclipse, я получаю сообщение "cat cat", которое гласит: "Нет реализации, найденной для native...". Есть ли что-то, что я пропускаю, так как все примеры NDK в C?
Благодарю.
11 ответов
Есть пара вещей, которые могут привести к тому, что "реализация не найдена". Один из них получает неправильное имя прототипа функции, другой вообще не может загрузить.so. Вы уверены, что System.loadLibrary()
вызывается перед использованием метода?
Если у вас нет JNI_OnLoad
После определения функции вы можете захотеть создать ее, чтобы она выдавала сообщение журнала, чтобы убедиться, что библиотека успешно загружена.
Вы уже избежали самой распространенной проблемы - забыли использовать extern "C"
- так что это или выше, или какая-то небольшая ошибка. Как выглядит объявление Java?
Дополнительная причина этой ошибки: ваше недокорированное имя собственного метода не должно содержать подчеркивания!
Например, я хотел экспортировать функцию C с именем AudioCapture_Ping()
, Вот моя экспортная декларация в C:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object); //Notice the underscore before Ping
Вот мой класс Java, импортирующий функцию:
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapture_Ping(); // FAILS
...
Я не мог заставить Android динамически связываться с моим собственным методом, пока я не удалил подчеркивание:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object);
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapturePing(); // THIS WORKS!
...
У меня была такая же проблема, но мне ошибка была в файле Android.mk. Я имел его:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp
но должно иметь это:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp
обратите внимание на детали += вместо :=
Надеюсь, это поможет.
Вызывается extern "C", как предусмотрено в автоматически сгенерированном примере Studio, но забыл обернуть весь остальной файл, включая следующие функции, в скобки {}. Работала только первая функция.
Пример приложения cpp в приложениях в ndk: https://android.googlesource.com/platform/development/+/marshmallow-release/ndk/platforms/android-5/samples/hello-gl2/jni/gl_code.cpp
Дополнительная причина: используйте LOCAL_WHOLE_STATIC_LIBRARIES вместо LOCAL_STATIC_LIBRARIES в android.mk. Это не позволяет библиотеке оптимизировать неиспользуемые вызовы API, поскольку NDK не может обнаружить использование собственных привязок из кода Java.
Если имя вашего пакета содержит символ _, вы должны написать 1(один) после символа _, как показано ниже:
MainActivity.java
package com.example.testcpp_2;
нативной lib.cpp
JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(
Используйте javah (часть Java SDK). Это инструмент именно для этого (генерирует заголовок.h из файла.class).
Я пробую все вышеперечисленные решения, но никто не может решить мою ошибку сборки (jni java.lang.UnsatisfiedLinkError: Реализация не найдена для...), наконец я обнаружил, что забыл добавить свой исходный файл verify.cpp в CMakeList.txt add_library segement(verify.cpp автоматически генерируется с помощью комбинации клавиш Ctrl + Enter, возможно, с другим именем файла), надеюсь, мой ответ может помочь кому-то.
моя среда сборки: Gradle + CMake
Я столкнулся с той же проблемой, и в моем случае причина была в том, что я подчеркнул в имени пакета "RFID_Test", я переименовал пакет, и он работал. Спасибо user1222021
Я сталкивался с одной и той же проблемой дважды. Случилось так, что телефон, который я пытался запустить из Android Studio, использовал уровень API, который я еще не загружал в Android Studio.
- Обновите Android Studio до последней версии
- Загрузите необходимый API из Android Studio