Ricerca…


introduzione

JNI (Java Native Interface) è un potente strumento che consente agli sviluppatori Android di utilizzare l'NDK e utilizzare il codice nativo C ++ nelle loro applicazioni. Questo argomento descrive l'utilizzo dell'interfaccia <-> C ++ Java.

Come chiamare le funzioni in una libreria nativa tramite l'interfaccia JNI

Java Native Interface (JNI) consente di chiamare funzioni native da codice Java e viceversa. Questo esempio mostra come caricare e chiamare una funzione nativa tramite JNI, non entra nell'accesso ai metodi e ai campi Java dal codice nativo utilizzando le funzioni JNI .

Supponiamo di avere una libreria nativa chiamata libjniexample.so nella libjniexample.so project/libs/<architecture> e si desidera chiamare una funzione dalla classe Java JNITest all'interno del pacchetto com.example.jniexample .

Nella classe JNITest, dichiara la funzione in questo modo:

public native int testJNIfunction(int a, int b);

Nel tuo codice nativo, definisci la funzione in questo modo:

#include <jni.h>

JNIEXPORT jint JNICALL Java_com_example_jniexample_JNITest_testJNIfunction(JNIEnv *pEnv, jobject thiz, jint a, jint b)
{
    return a + b;
}

L'argomento pEnv è un puntatore all'ambiente JNI che è possibile passare alle funzioni JNI per accedere a metodi e campi di oggetti e classi Java. Il puntatore thiz è un riferimento di jobject all'oggetto Java su cui è stato chiamato il metodo nativo (o la classe se si tratta di un metodo statico).

Nel tuo codice Java, in JNITest , carica la libreria in questo modo:

static{
    System.loadLibrary("jniexample");
}

Notare la lib all'inizio e il .so alla fine del nome del file sono omessi.

Chiama la funzione nativa da Java in questo modo:

JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);

Come chiamare un metodo Java dal codice nativo

Java Native Interface (JNI) consente di chiamare le funzioni Java dal codice nativo. Ecco un semplice esempio di come farlo:

Codice Java:

package com.example.jniexample;
public class JNITest {
    public static int getAnswer(bool) {
        return 42;
    }
}

Codice 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 metodo JNI in tipo Java:

Firma JNI Tipo Java
Z booleano
B byte
C carbonizzare
S corto
io int
J lungo
F galleggiante
D Doppio
L classe pienamente qualificata; fully-qualified di classe
[ genere genere[]

Quindi per il nostro esempio abbiamo usato (Z) I - il che significa che la funzione ottiene un valore booleano e restituisce un int.

Metodo di utilità nel livello JNI

Questo metodo aiuterà a ottenere la stringa Java dalla stringa 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;
    }

Questo metodo ti aiuterà a convertire jbyteArray in 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow