Android
Android Javaネイティブインタフェース(JNI)
サーチ…
前書き
JNI (Java Native Interface)は、Android開発者がアプリケーションでNDKを使用してC ++ネイティブコードを使用できる強力なツールです。このトピックでは、Java < - > C ++インタフェースの使用法について説明します。
JNIインタフェースを介してネイティブライブラリ内の関数を呼び出す方法
Javaネイティブインタフェース (JNI)を使用すると、Javaコードからネイティブ関数を呼び出すことができます。この例では、JNIを使用してネイティブ関数をロードおよびコールする方法を示します.JNI関数を使用してネイティブコードからJavaメソッドおよびフィールドにアクセスすることはありません。
project/libs/<architecture>
フォルダにlibjniexample.so
という名前のネイティブライブラリがあり、 com.example.jniexample
パッケージ内のJNITest
Javaクラスから関数を呼び出したいとします。
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
引数は、JavaオブジェクトおよびクラスのメソッドおよびフィールドにアクセスするためにJNI関数に渡すことができるJNI環境へのポインタです。 thiz
ポインタは、ネイティブメソッドが呼び出されたJavaオブジェクト(静的メソッドの場合はクラス)へのjobject
参照です。
JavaコードのJNITest
、次のようにライブラリをロードします。
static{
System.loadLibrary("jniexample");
}
開始時のlib
に注意してください。ファイル名の末尾にある.so
は省略されています。
Javaのネイティブ関数を次のように呼び出します。
JNITest test = new JNITest();
int c = test.testJNIfunction(3, 4);
ネイティブコードからJavaメソッドを呼び出す方法
Javaネイティブインタフェース(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 | ブール値 |
B | バイト |
C | チャー |
S | ショート |
私 | int |
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;
}