Beispiel: hello-jni

Dieses Beispiel führt Sie durch hello-jni, eine minimale C/C++-Anwendung, die mit dem NDK erstellt wurde. Dieses Beispiel befindet sich im Verzeichnis hello-jni des Repositorys ndk-sample im android-mk-Branch.

Android.Mk

Die folgenden beiden Zeilen geben den Namen der nativen Quelldatei zusammen mit dem Namen der gemeinsam genutzten Bibliothek an, die erstellt werden soll. Der vollständige Name der erstellten Bibliothek lautet libhello-jni.so, sobald das Build-System das Präfix lib und die Erweiterung .so hinzugefügt hat.

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

Weitere Informationen zur Funktion und Verwendung der Datei Android.mk findest du unter Android.mk.

Anwendung.Mk

Diese Zeile teilt dem Build-System die CPU und die Architektur mit, für die es erstellt werden soll. In diesem Beispiel wird das Build-System für alle unterstützten Architekturen erstellt.

APP_ABI := all

Weitere Informationen zur Datei Application.mk und ihrer Verwendung finden Sie unter Application.mk.

Java-seitige Implementierung

Die Datei helloJNI.java befindet sich in hellojni/src/com/example/hellojni/. Sie ruft eine Funktion auf, um einen String von der nativen Seite abzurufen, und zeigt ihn dann auf dem Bildschirm an.

Der Quellcode enthält drei Zeilen, die für den NDK-Nutzer besonders interessant sind. Sie werden hier in der Reihenfolge angezeigt, in der sie verwendet werden, und nicht in Zeilenreihenfolge.

Mit diesem Funktionsaufruf wird die Datei .so beim Start der Anwendung geladen.

Kotlin

System.loadLibrary("hello-jni")

Java

System.loadLibrary("hello-jni");

Das Schlüsselwort native in dieser Methodendeklaration teilt der virtuellen Maschine mit, dass sich die Funktion in der gemeinsam genutzten Bibliothek befindet, das heißt, auf der nativen Seite implementiert ist.

Kotlin

external fun stringFromJNI(): String

Java

public native String stringFromJNI();

Das Android-Framework ruft die in den vorherigen Schritten geladene und deklarierte Funktion auf und zeigt den String auf dem Bildschirm an.

Kotlin

tv.text = stringFromJNI()

Java

tv.setText( stringFromJNI() );

C-Side-Implementierung

Die Datei hello-jni.c befindet sich in hello-jni/jni/. Sie enthält eine Funktion, die einen String zurückgibt, der von der Java-Seite angefordert wurde. Die Funktionsdeklaration lautet:

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

Diese Deklaration entspricht der nativen Funktion, die im Java-Quellcode deklariert ist. Der Rückgabetyp jstring ist ein Datentyp, der in der Spezifikation für native Java-Schnittstellen definiert ist. Er ist kein String, sondern ein Zeiger auf einen Java-String.

Nach jstring steht der Funktionsname, der auf dem Namen der Java-Funktion und dem Pfad zu der Datei basiert, die ihn enthält. konstruieren Sie diese nach den folgenden Regeln:

  • Stellen Sie ihm Java_ voran.
  • Geben Sie den Dateipfad im Verhältnis zum Quellverzeichnis der obersten Ebene an.
  • Verwenden Sie Unterstriche anstelle von Schrägstrichen.
  • Lassen Sie die Dateiendung .java weg.
  • Hängen Sie nach dem letzten Unterstrich den Funktionsnamen an.

Gemäß diesen Regeln wird in diesem Beispiel der Funktionsname Java_com_example_hellojni_HelloJni_stringFromJNI verwendet. Dieser Name bezieht sich auf die Java-Funktion stringFromJNI(), die sich in hellojni/src/com/example/hellojni/HelloJni.java befindet.

JNIEnv* ist der Zeiger auf die VM und jobject ist ein Zeiger auf das implizite this-Objekt, das von der Java-Seite übergeben wird.

Die folgende Zeile ruft die VM API (*env) auf und übergibt ihr einen Rückgabewert, also den String, den die Funktion auf Java-Seite angefordert hat.

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