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;
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow