Sök…


Introduktion

JNI (Java Native Interface) är ett kraftfullt verktyg som gör det möjligt för Android-utvecklare att använda NDK och använda C ++ native code i sina applikationer. Detta ämne beskriver användningen av Java <-> C ++ -gränssnitt.

Hur man ringer till funktioner i ett inbyggt bibliotek via JNI-gränssnittet

Java Native Interface (JNI) låter dig ringa inbyggda funktioner från Java-kod och vice versa. Det här exemplet visar hur du laddar och anropar en inbyggd funktion via JNI, den går inte till åtkomst till Java-metoder och fält från inbyggd kod med hjälp av JNI-funktioner .

Anta att du har ett ursprungligt bibliotek med namnet libjniexample.so i libjniexample.so project/libs/<architecture> , och du vill ringa en funktion från JNITest Java-klassen i paket com.example.jniexample .

Förklara funktionen på JNITest-klassen:

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

Definiera funktionen på följande sätt i din inbyggda kod:

#include <jni.h>

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

Argumentet pEnv är en pekare till JNI-miljön som du kan överföra till JNI-funktioner för att komma åt metoder och fält för Java-objekt och klasser. Den thiz pekaren är en referens till jobject till Java-objektet som den ursprungliga metoden kallades på (eller klassen om det är en statisk metod).

I din Java-kod, i JNITest , laddar du biblioteket så här:

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

Notera lib i början och .so i slutet av filnamnet utelämnas.

Ring den ursprungliga funktionen från Java så här:

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

Hur man ringer en Java-metod från inbyggd kod

Java Native Interface (JNI) låter dig ringa Java-funktioner från inbyggd kod. Här är ett enkelt exempel på hur du gör det:

Java-kod:

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

Infödningskod:

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

JNI-metodsignatur till Java-typ:

JNI Signatur Java-typ
Z boolean
B bitgrupp
C röding
S kort
jag int
J lång
F flyta
D dubbel-
L fullt kvalificerad klass; fullt kvalificerade-klass
[typ typ[]

Så för vårt exempel använde vi (Z) I - vilket betyder att funktionen får en booleska och returnerar en int.

Verktygsmetod i JNI-lager

Den här metoden hjälper till att hämta Java-strängen från C ++ -strängen.

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

Den här metoden hjälper dig att konvertera jbyteArray till 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow