Android
Interfaz nativa de Java para Android (JNI)
Buscar..
Introducción
JNI (Java Native Interface) es una poderosa herramienta que permite a los desarrolladores de Android utilizar el NDK y utilizar el código nativo de C ++ en sus aplicaciones. Este tema describe el uso de la interfaz Java <-> C ++.
Cómo llamar a funciones en una biblioteca nativa a través de la interfaz JNI
La interfaz nativa de Java (JNI) le permite llamar a funciones nativas desde el código de Java y viceversa. Este ejemplo muestra cómo cargar y llamar a una función nativa a través de JNI, no se utiliza para acceder a los métodos y campos de Java desde el código nativo mediante las funciones de JNI .
Supongamos que tiene una biblioteca nativa llamada libjniexample.so
en la carpeta project/libs/<architecture>
y desea llamar a una función de la clase Java de JNITest
dentro del paquete com.example.jniexample
.
En la clase JNITest, declare la función así:
public native int testJNIfunction(int a, int b);
En su código nativo, defina la función así:
#include <jni.h>
JNIEXPORT jint JNICALL Java_com_example_jniexample_JNITest_testJNIfunction(JNIEnv *pEnv, jobject thiz, jint a, jint b)
{
return a + b;
}
El argumento pEnv
es un puntero al entorno JNI que puede pasar a las funciones JNI para acceder a métodos y campos de objetos y clases de Java. El thiz
puntero es un jobject
referencia al objeto de Java que el método nativo fue llamado (o la clase si se trata de un método estático).
En su código Java, en JNITest
, cargue la biblioteca así:
static{
System.loadLibrary("jniexample");
}
Tenga en cuenta la lib
al principio, y .so
al final del nombre de archivo se omiten.
Llama a la función nativa desde Java así:
JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);
Cómo llamar a un método Java desde código nativo
La interfaz nativa de Java (JNI) le permite llamar a funciones Java desde código nativo. Aquí hay un ejemplo simple de cómo hacerlo:
Código de Java:
package com.example.jniexample;
public class JNITest {
public static int getAnswer(bool) {
return 42;
}
}
Código nativo:
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);
}
Firma del método JNI al tipo Java:
JNI Signature | Tipo de Java |
---|---|
Z | booleano |
segundo | byte |
do | carbonizarse |
S | corto |
yo | En t |
J | largo |
F | flotador |
re | doble |
L clase completamente calificada; | clase completamente calificada |
[ tipo | tipo[] |
Así que para nuestro ejemplo usamos (Z) I, lo que significa que la función obtiene un valor booleano y devuelve un int.
Método de utilidad en la capa JNI
Este método ayudará a obtener la cadena Java de la cadena 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;
}
Este método te ayudará a convertir jbyteArray a 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;
}