Android
Android Java Native Interface (JNI)
Szukaj…
Wprowadzenie
JNI (Java Native Interface) to potężne narzędzie, które umożliwia programistom Androida korzystanie z NDK i używanie natywnego kodu C ++ w swoich aplikacjach. W tym temacie opisano użycie interfejsu Java <-> C ++.
Jak wywoływać funkcje w rodzimej bibliotece za pośrednictwem interfejsu JNI
Interfejs Java Native (JNI) umożliwia wywoływanie funkcji rodzimych z kodu Java i odwrotnie. Ten przykład pokazuje, jak załadować i wywołać funkcję rodzimą za pomocą JNI, nie ma ona dostępu do metod i pól Java z kodu rodzimego za pomocą funkcji JNI .
Załóżmy, że masz natywną bibliotekę o nazwie libjniexample.so
w libjniexample.so
project/libs/<architecture>
i chcesz wywołać funkcję z klasy JNITest
Java w pakiecie com.example.jniexample
.
W klasie JNITest zadeklaruj funkcję w następujący sposób:
public native int testJNIfunction(int a, int b);
W kodzie natywnym zdefiniuj funkcję w następujący sposób:
#include <jni.h>
JNIEXPORT jint JNICALL Java_com_example_jniexample_JNITest_testJNIfunction(JNIEnv *pEnv, jobject thiz, jint a, jint b)
{
return a + b;
}
Argument pEnv
jest wskaźnikiem do środowiska JNI, który można przekazać do funkcji JNI w celu uzyskania dostępu do metod i pól obiektów i klas Java. thiz
wskaźnik jest jobject
Odwołanie do obiektu Java, że metoda została wywołana na rodzimy (lub klasy, jeśli jest to metoda statyczna).
W kodzie Java w JNITest
załaduj bibliotekę w następujący sposób:
static{
System.loadLibrary("jniexample");
}
Zwróć uwagę na lib
na początku, a .so
na końcu nazwy pliku jest pomijane.
Wywołaj natywną funkcję z Java w następujący sposób:
JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);
Jak wywołać metodę Java z kodu natywnego
Java Native Interface (JNI) pozwala na wywoływanie funkcji Java z kodu natywnego. Oto prosty przykład, jak to zrobić:
Kod Java:
package com.example.jniexample;
public class JNITest {
public static int getAnswer(bool) {
return 42;
}
}
Kod macierzysty:
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);
}
Podpis metody JNI dla typu Java:
Podpis JNI | Typ Java |
---|---|
Z | boolean |
b | bajt |
do | zwęglać |
S. | krótki |
ja | int |
jot | długo |
fa | pływak |
re | podwójnie |
L w pełni kwalifikowana klasa; | w pełni wykwalifikowana klasa |
[ rodzaj | rodzaj[] |
Więc w naszym przykładzie użyliśmy (Z) I - co oznacza, że funkcja otrzymuje wartość logiczną i zwraca liczbę całkowitą.
Metoda użyteczności w warstwie JNI
Ta metoda pomoże uzyskać ciąg Java z ciągu 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;
}
Ta metoda pomoże ci przekonwertować jbyteArray na 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;
}