Android
Android Java Native Interface (JNI)
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;
}