サーチ…


前書き

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


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow