Пример: привет-джни

В этом примере вы познакомитесь с hello-jni — минимальным приложением C/C++, созданным с помощью NDK. Этот образец находится в каталоге hello-jni репозитория ndk-samples внутри ветки android-mk .

Android.mk

Следующие две строки содержат имя собственного исходного файла, а также имя общей библиотеки для сборки. Полное имя собранной библиотеки — libhello-jni.so , как только система сборки добавляет префикс lib и расширение .so .

LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE    := hello-jni

Дополнительные сведения о том, что делает файл Android.mk и как его использовать, см. в разделе Android.mk .

Приложение.мк

Эта строка сообщает системе сборки процессор и архитектуру, на основе которой следует выполнять сборку. В этом примере система сборки строится для всех поддерживаемых архитектур.

APP_ABI := all

Дополнительные сведения о файле Application.mk и о том, как его использовать, см. в разделе Application.mk .

Реализация на стороне Java

Файл helloJNI.java находится в hellojni/src/com/example/hellojni/ . Он вызывает функцию для получения строки с собственной стороны, а затем отображает ее на экране.

Исходный код содержит три строки, представляющие особый интерес для пользователя NDK. Здесь они представлены в том порядке, в котором они используются, а не в порядке строк.

Этот вызов функции загружает файл .so при запуске приложения.

Котлин

System.loadLibrary("hello-jni")

Ява

System.loadLibrary("hello-jni");

Ключевое слово native в объявлении этого метода сообщает виртуальной машине, что функция находится в общей библиотеке (то есть реализована на собственной стороне).

Котлин

external fun stringFromJNI(): String

Ява

public native String stringFromJNI();

Платформа Android вызывает функцию, загруженную и объявленную на предыдущих шагах, отображая строку на экране.

Котлин

tv.text = stringFromJNI()

Ява

tv.setText( stringFromJNI() );

Реализация C-стороны

Файл hello-jni.c находится в папке hello-jni/jni/ . Он содержит функцию, возвращающую строку, запрошенную стороной Java ). Объявление функции выглядит следующим образом:

JNIEXPORT jstring JNICALL
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )

Это объявление соответствует встроенной функции, объявленной в исходном коде Java. Возвращаемый тип jstring — это тип данных, определенный в спецификации Java Native Interface . На самом деле это не строка, а указатель на строку Java.

После jstring следует имя функции, которое основано на имени функции Java и пути к содержащему ее файлу. Постройте его по следующим правилам:

  • Добавьте к нему Java_ .
  • Опишите путь к файлу относительно исходного каталога верхнего уровня.
  • Используйте подчеркивание вместо косой черты.
  • Опустите расширение файла .java .
  • После последнего подчеркивания добавьте имя функции.

Следуя этим правилам, в этом примере используется имя функции Java_com_example_hellojni_HelloJni_stringFromJNI . Это имя относится к функции Java под названием stringFromJNI() , которая находится в hellojni/src/com/example/hellojni/HelloJni.java .

JNIEnv* — это указатель на виртуальную машину, а jobject — это указатель на неявный объект this , переданный со стороны Java.

Следующая строка вызывает API VM (*env) и передает ему возвращаемое значение: то есть строку, запрошенную функцией на стороне Java.

return (*env)->NewStringUTF(env, "Hello from JNI !
Compiled with ABI " ABI ".");