NDK開発の配列操作
JNIはJava配列を参照型として処理し,JNIはJava配列にアクセスして処理するために必要な関数を提供する.
次は一つ一つ見てみましょう.
1.配列を作成するには、NewArray関数を使用して、元のコードに配列インスタンスを作成します.ここでは、Int、Char、Booleanなどです.NewIntArrayなどです.これらの関数を使用する場合は、配列のサイズをパラメータとして指定する必要があります.次のコードを見てください.
まずjintArray配列を定義し、次にjint配列を定義し、jint配列の内容をjintArrayにコミットし、jintArrayに戻ります.
NewString関数と同様に、メモリがオーバーフローした場合、NewArray関数はNULLを返し、ネイティブコード仮想マシンに異常放出があることを通知し、ネイティブコードが停止します.
2.配列要素JNIにアクセスするには、Java配列要素にアクセスする2つの方法があります.Java配列をC配列にコピーするか、配列要素に直接ポインタを与えることができます.この2つの方法をそれぞれ紹介します.
2.1レプリカの操作Java配列をC配列にコピーし、その配列を操作できます.次のコードを見て、Javaが配列を転送し、配列要素の和を計算して戻ります.
オリジナルコードは、通常のC配列を使用するように配列要素を使用および変更できます.元のコード相が行った変更をJava配列にコミットする場合、SetArrayRegion関数を使用してC配列をJava配列にコピーできます.次のコードを見て、Javaが転送した配列の各要素に1を加えて、修正した配列を返します.
2.2ダイレクトポインタの操作
生コードはGetArrayElements関数を用いて配列要素への直接ポインタを取得することができる.3番目のパラメータは、前回のブログで述べたように、isCopyという名前のオプションパラメータであり、呼び出し元に返されるC文字列アドレスがコピーを指すか、スタック内の固定オブジェクトを指すかを決定させる.
通常のC配列のように配列要素にアクセスして処理することができるため、JNIは要素にアクセスして処理する方法を提供していない.JNIは原生コードが切れたらこれらのポインタをすぐに解放しなければならない.そうしないとメモリオーバーフローの問題が発生し、原生コードはJNIが提供したReleaseArrayElements関数を使用してGetArrayElements関数が返したC配列を解放することができる.この関数には4つのパラメータがあり,4つ目は解放モードであり,以下の3つがある.
今回はCを用いて簡単な乗算を行い,Javaは配列を伝え,その配列の要素を蓄積して返す.
はい、配列操作についてはこれだけです.問題があれば、伝言討論を歓迎します.
次は一つ一つ見てみましょう.
1.配列を作成するには、NewArray関数を使用して、元のコードに配列インスタンスを作成します.ここでは、Int、Char、Booleanなどです.NewIntArrayなどです.これらの関数を使用する場合は、配列のサイズをパラメータとして指定する必要があります.次のコードを見てください.
まずjintArray配列を定義し、次にjint配列を定義し、jint配列の内容をjintArrayにコミットし、jintArrayに戻ります.
jintArray Java_com_example_jni_MainActivity_getIntArray(JNIEnv* env,
jobject thiz) {
jintArray javaArray;
jint nativeArr[3] = {21,22,23};
javaArray = (*env)->NewIntArray(env,3);
(*env)->SetIntArrayRegion(env,javaArray,0,3,nativeArr);
return javaArray;
}
NewString関数と同様に、メモリがオーバーフローした場合、NewArray関数はNULLを返し、ネイティブコード仮想マシンに異常放出があることを通知し、ネイティブコードが停止します.
2.配列要素JNIにアクセスするには、Java配列要素にアクセスする2つの方法があります.Java配列をC配列にコピーするか、配列要素に直接ポインタを与えることができます.この2つの方法をそれぞれ紹介します.
2.1レプリカの操作Java配列をC配列にコピーし、その配列を操作できます.次のコードを見て、Javaが配列を転送し、配列要素の和を計算して戻ります.
jint Java_com_example_jni_MainActivity_getSum(JNIEnv* env,
jobject thiz,jintArray javaArray) {
// Java
jsize length = (*env)->GetArrayLength(env,javaArray);
// C
jint nativeArr[length];
jint sum = 0;
// Java C
(*env)->GetIntArrayRegion(env,javaArray,0,length,nativeArr);
int i;
//
for(i=0;i<length;i++){
sum+=nativeArr[i];
}
return sum;
}
オリジナルコードは、通常のC配列を使用するように配列要素を使用および変更できます.元のコード相が行った変更をJava配列にコミットする場合、SetArrayRegion関数を使用してC配列をJava配列にコピーできます.次のコードを見て、Javaが転送した配列の各要素に1を加えて、修正した配列を返します.
jintArray Java_com_example_jni_MainActivity_arrAdd1(JNIEnv* env,
jobject thiz,jintArray javaArray) {
// Java
jsize length = (*env)->GetArrayLength(env,javaArray);
// C
// Java C
jint nativeArr[length];
(*env)->GetIntArrayRegion(env,javaArray,0,length,nativeArr);
int i;
//
for(i=0;i<length;i++){
nativeArr[i]=nativeArr[i]+1;
}
// C Java
(*env)->SetIntArrayRegion(env,javaArray,0,length,nativeArr);
return javaArray;
}
2.2ダイレクトポインタの操作
生コードはGetArrayElements関数を用いて配列要素への直接ポインタを取得することができる.3番目のパラメータは、前回のブログで述べたように、isCopyという名前のオプションパラメータであり、呼び出し元に返されるC文字列アドレスがコピーを指すか、スタック内の固定オブジェクトを指すかを決定させる.
通常のC配列のように配列要素にアクセスして処理することができるため、JNIは要素にアクセスして処理する方法を提供していない.JNIは原生コードが切れたらこれらのポインタをすぐに解放しなければならない.そうしないとメモリオーバーフローの問題が発生し、原生コードはJNIが提供したReleaseArrayElements関数を使用してGetArrayElements関数が返したC配列を解放することができる.この関数には4つのパラメータがあり,4つ目は解放モードであり,以下の3つがある.
0:
JNI_COMMIT: , Java 。
JNI_ABORT 。
今回はCを用いて簡単な乗算を行い,Javaは配列を伝え,その配列の要素を蓄積して返す.
jint Java_com_example_jni_MainActivity_multiplication(JNIEnv* env,jobject thiz,jintArray javaArray){
jint* nativeDirectArray;
jboolean isCopy;
jint result = 1;
jsize length = (*env)->GetArrayLength(env,javaArray);
nativeDirectArray = (*env)->GetIntArrayElements(env,javaArray,&isCopy);
int i = 0;
for(i=0;i<length;i++){
result *= nativeDirectArray[i];
}
(*env)->ReleaseIntArrayElements(env,javaArray,nativeDirectArray,0);
return result;
}
はい、配列操作についてはこれだけです.問題があれば、伝言討論を歓迎します.