JNIを使ってみる(3) 配列を扱う
k.tsuka
今回は、Java⇔Jniで配列を入出力する方法を紹介します。

まずはじめに、Jniではプリミティブな型を別名定義していますので、配列も型宣言が異なります。型定義を下表にまとめましたので確認しておいてください。

Java  Jni 
単体 配列
boolean jboolean jbooleanArray
byte jbyte jbyteArray
char jchar jcharArray
short jshort jshortArray
int jint jintArray
long jlong jlongArray
float jfloat jfloatArray
double jdouble jdoubleArray



また、JavaとC/C++では配列の扱い方が異なるため、変換関数がそれぞれのプリミティブ型毎に用意されています。
変換用に用意されているメソッドは以下の4種類です。

  プロトタイプ(Byte型の例) 備考 
新規作成  jbyteArray NewByteArray(JNIEnv* env, jsize length)  
配列長取得 jsize GetArrayLength(JNIEnv* env, jarray array)  
要素列取得 jbyte* GetByteArrayElements(JNIEnv* env, jintArray array, jboolean *isCopy)  
要素解放 void ReleaseByteArrayElements(JNIEnv* env, jintArray array, jbyte* elems, jbyte mode)  

cf)
  int型の場合、新規作成メソッドは、 jintArray NewIntArray(JNIEnv* env, jsize length) となります。
  使用する型に応じてメソッド名や戻り値型を変更させて使用してください。

それではサンプルコードを紹介します。
紹介するサンプルは、native上で生成したchar型配列をjbyteArrayに変換するメソッドになります。



jbyteArray createByteArray(JNIEnv* env, char* array, int len, jbyte** tmp) {

	int cnt = 0;
	/* jbyteArray用のメモリを確保 */
	jbyteArray ret = (*env)->NewByteArray(env, len);
	/* jbyteArrayの参照ポインタ取得 */
	jbyte* b = (*env)->GetByteArrayElements(env, ret, 0);

	for(cnt = 0; cnt < len; cnt++){
		/* 要素を詰め替え */
		b[cnt] = (jbyte)array[cnt];
	}
	/* 解放用に出力引数に設定 */
	*tmp = b;
	/* jbyteArrayを返却 */
	return ret;
}



呼び出し側は下のようなイメージでjbyteArrayを生成します。

void sample(JNIEnv* env, jobject thiz, char * arr) {
	jbyte*     tmp;
	jbyteArray byteArray;

	/* jbyteArrayを作成 */
	jbyteArray = createByteArray(env, arr, sizeof(arr), &tmp);

	/* ここでjavaにコールバックを返すなどjbyteArrayを使用する処理を行う */

	/* jbyteArrayが使用しているメモリを確保 */
	(*env)->ReleaseByteArrayElements(env, re, tmp, 0);
}

jbyteArray型をbyte[]に変換する場合は、上記サンプルと同様にGetByteArrayElements()で得られる参照ポインタを使用して、C/C++で定義したbyte[]の各要素を詰め替えを行ってください。


参考にしたサイトおよび資料

    基礎から学ぶ組み込みAndroid



inserted by FC2 system