Android
Android Java Native Interface (JNI)
Recherche…
Introduction
JNI (Java Native Interface) est un outil puissant qui permet aux développeurs Android d'utiliser le NDK et d'utiliser du code natif C ++ dans leurs applications. Cette rubrique décrit l'utilisation de l'interface Java <-> C ++.
Comment appeler des fonctions dans une bibliothèque native via l'interface JNI
L’ interface Java native (JNI) vous permet d’appeler des fonctions natives à partir du code Java et inversement. Cet exemple montre comment charger et appeler une fonction native via JNI, il n'entre pas dans l'accès aux méthodes et champs Java à partir du code natif à l'aide des fonctions JNI .
Supposons que vous ayez une bibliothèque native nommée libjniexample.so
dans le dossier project/libs/<architecture>
et que vous souhaitiez appeler une fonction de la classe Java JNITest
dans le package com.example.jniexample
.
Dans la classe JNITest, déclarez la fonction comme ceci:
public native int testJNIfunction(int a, int b);
Dans votre code natif, définissez la fonction comme ceci:
#include <jni.h>
JNIEXPORT jint JNICALL Java_com_example_jniexample_JNITest_testJNIfunction(JNIEnv *pEnv, jobject thiz, jint a, jint b)
{
return a + b;
}
L'argument pEnv
est un pointeur sur l'environnement JNI que vous pouvez transmettre aux fonctions JNI pour accéder aux méthodes et aux champs d'objets et de classes Java. Le pointeur thiz
est une référence de jobject
à l'objet Java sur lequel la méthode native a été appelée (ou la classe s'il s'agit d'une méthode statique).
Dans votre code Java, dans JNITest
, chargez la bibliothèque comme JNITest
:
static{
System.loadLibrary("jniexample");
}
Notez la lib
au début, et le .so
à la fin du nom de fichier est omis.
Appelez la fonction native à partir de Java comme ceci:
JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);
Comment appeler une méthode Java à partir du code natif
L'interface Java native (JNI) vous permet d'appeler des fonctions Java à partir de code natif. Voici un exemple simple de comment le faire:
Code Java:
package com.example.jniexample;
public class JNITest {
public static int getAnswer(bool) {
return 42;
}
}
Code natif:
int getTheAnswer()
{
// Get JNI environment
JNIEnv *env = JniGetEnv();
// Find the Java class - provide package ('.' replaced to '/') and class name
jclass jniTestClass = env->FindClass("com/example/jniexample/JNITest");
// Find the Java method - provide parameters inside () and return value (see table below for an explanation of how to encode them)
jmethodID getAnswerMethod = env->GetStaticMethodID(jniTestClass, "getAnswer", "(Z)I;");
// Calling the method
return (int)env->CallStaticObjectMethod(jniTestClass, getAnswerMethod, (jboolean)true);
}
Signature de la méthode JNI vers le type Java:
Signature JNI | Type Java |
---|---|
Z | booléen |
B | octet |
C | carboniser |
S | court |
je | int |
J | longue |
F | flotte |
ré | double |
L classe entièrement qualifiée; | classe qualifiée |
[type | type[] |
Donc, pour notre exemple, nous avons utilisé (Z) I - ce qui signifie que la fonction obtient un booléen et renvoie un int.
Méthode utilitaire dans la couche JNI
Cette méthode aidera à obtenir la chaîne Java de la chaîne C ++.
jstring getJavaStringFromCPPString(JNIEnv *global_env, const char* cstring) {
jstring nullString = global_env->NewStringUTF(NULL);
if (!cstring) {
return nullString;
}
jclass strClass = global_env->FindClass("java/lang/String");
jmethodID ctorID = global_env->GetMethodID(strClass, "<init>",
"([BLjava/lang/String;)V");
jstring encoding = global_env->NewStringUTF("UTF-8");
jbyteArray bytes = global_env->NewByteArray(strlen(cstring));
global_env->SetByteArrayRegion(bytes, 0, strlen(cstring), (jbyte*) cstring);
jstring str = (jstring) global_env->NewObject(strClass, ctorID, bytes,
encoding);
global_env->DeleteLocalRef(strClass);
global_env->DeleteLocalRef(encoding);
global_env->DeleteLocalRef(bytes);
return str;
}
Cette méthode vous aidera à convertir jbyteArray en char
char* as_unsigned_char_array(JNIEnv *env, jbyteArray array) {
jsize length = env->GetArrayLength(array);
jbyte* buffer = new jbyte[length + 1];
env->GetByteArrayRegion(array, 0, length, buffer);
buffer[length] = '\0';
return (char*) buffer;
}