Android
Интерфейс Java Java Native (JNI)
Поиск…
Вступление
JNI (Java Native Interface) - это мощный инструмент, который позволяет разработчикам Android использовать NDK и использовать собственный код C ++ в своих приложениях. В этом разделе описывается использование интерфейса Java <-> C ++.
Как вызвать функции в собственной библиотеке через интерфейс JNI
Интерфейс Java Native (JNI) позволяет вам вызывать собственные функции из кода Java и наоборот. В этом примере показано, как загружать и вызывать собственную функцию через JNI, она не переходит к доступу к методам и полям Java из собственного кода с использованием функций JNI .
Предположим, у вас есть родная библиотека с именем libjniexample.so
в libjniexample.so
project/libs/<architecture>
, и вы хотите вызвать функцию из класса JNITest
Java внутри пакета com.example.jniexample
.
В классе JNITest объявите функцию следующим образом:
public native int testJNIfunction(int a, int b);
В вашем собственном коде определите функцию следующим образом:
#include <jni.h>
JNIEXPORT jint JNICALL Java_com_example_jniexample_JNITest_testJNIfunction(JNIEnv *pEnv, jobject thiz, jint a, jint b)
{
return a + b;
}
Аргумент pEnv
является указателем на среду JNI, которую вы можете передать функциям JNI для доступа к методам и полям объектов и классов Java. thiz
указатель является jobject
ссылки на объект Java , который нативный метод был вызван (или класс , если это статический метод).
В вашем Java-коде в JNITest
загрузите библиотеку следующим образом:
static{
System.loadLibrary("jniexample");
}
Обратите внимание на lib
в начале, а .so
в конце имени файла опущены.
Вызовите функцию native из Java следующим образом:
JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);
Как вызвать метод Java из собственного кода
Интерфейс Java Native Interface (JNI) позволяет вам вызывать функции Java из собственного кода. Вот простой пример того, как это сделать:
Код Java:
package com.example.jniexample;
public class JNITest {
public static int getAnswer(bool) {
return 42;
}
}
Родной код:
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-метода к типу Java:
Подпись JNI | Тип Java |
---|---|
Z | логический |
В | байт |
С | голец |
S | короткая |
я | ИНТ |
J | долго |
F | поплавок |
D | двойной |
L полностью квалифицированный класс; | полностью квалифицирован-класс |
[ тип | тип[] |
Итак, для нашего примера мы использовали (Z) I - что означает, что функция получает логическое значение и возвращает int.
Утилитный метод в слое JNI
Этот метод поможет получить строку Java из строки 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;
}
Этот метод поможет вам преобразовать jbyteArray в 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;
}