Exemple : hello-jni

Cet exemple vous présente hello-jni, une application C/C++ minimale créée avec le NDK. Vous le trouverez dans le répertoire hello-jni du dépôt ndk-samples, dans la branche android-mk.

Android.mk

Les deux lignes suivantes indiquent le nom du fichier source natif, avec le nom de la bibliothèque partagée à compiler. Le nom complet de la bibliothèque compilée est libhello-jni.so, une fois que le système de compilation a ajouté le préfixe lib et l'extension .so.

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

Pour en savoir plus sur le fichier Android.mk et son utilisation, consultez Android.mk.

Application.mk

Cette ligne indique au système de compilation le processeur et l'architecture avec lesquels la compilation doit avoir lieu. Dans cet exemple, le système de compilation compile toutes les architectures compatibles.

APP_ABI := all

Pour en savoir plus sur le fichier Application.mk et sur son utilisation, consultez Application.mk.

Implémentation côté Java

Le fichier helloJNI.java se trouve dans hellojni/src/com/example/hellojni/. Il appelle une fonction pour récupérer une chaîne du côté natif, puis l'affiche à l'écran.

Le code source contient trois lignes présentant un intérêt particulier pour l'utilisateur du NDK. Elles apparaissent dans l'ordre dans lequel elles sont utilisées, plutôt que selon l'ordre des lignes.

Cet appel de fonction charge le fichier .so au démarrage de l'application.

Kotlin

System.loadLibrary("hello-jni")

Java

System.loadLibrary("hello-jni");

Le mot clé native de cette déclaration de méthode indique à la machine virtuelle que la fonction se trouve dans la bibliothèque partagée (autrement dit, qu'elle est implémentée du côté natif).

Kotlin

external fun stringFromJNI(): String

Java

public native String stringFromJNI();

Le framework Android appelle la fonction chargée et déclarée lors des étapes précédentes, en affichant la chaîne à l'écran.

Kotlin

tv.text = stringFromJNI()

Java

tv.setText( stringFromJNI() );

Implémentation côté C

Le fichier hello-jni.c se trouve dans hello-jni/jni/. Il contient une fonction qui renvoie une chaîne demandée par le côté Java. La déclaration de la fonction est la suivante :

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

Cette déclaration correspond à la fonction native déclarée dans le code source Java. Le type renvoyé, jstring, est un type de données défini dans la spécification de l'interface native Java. Il ne s'agit pas d'une chaîne, mais d'un pointeur vers une chaîne Java.

Après jstring, vient le nom de la fonction. Il est basé sur le nom de la fonction Java et sur le chemin d'accès au fichier correspondant. Créez-le selon les règles suivantes :

  • Faites-le précéder de Java_.
  • Décrivez le chemin d'accès du fichier par rapport au répertoire source de premier niveau.
  • Utilisez des traits de soulignement à la place des barres obliques.
  • Omettez l'extension de fichier .java.
  • Ajoutez le nom de la fonction après le dernier trait de soulignement.

Cet exemple, qui respecte ces règles, utilise le nom de fonction Java_com_example_hellojni_HelloJni_stringFromJNI. Ce nom fait référence à une fonction Java appelée stringFromJNI(), qui réside dans hellojni/src/com/example/hellojni/HelloJni.java.

JNIEnv* est le pointeur vers la VM, et jobject est un pointeur vers l'objet this implicite transmis à partir du côté Java.

La ligne suivante appelle l'API VM (*env) et lui transmet une valeur renvoyée, à savoir la chaîne demandée par la fonction Java.

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