1. 引子
JNI 中的数组分为基本类型数组和对象数组,它们的处理方式是不一样的,基本类型数组中的所有元素都是 JNI的基本数据类型,可以直接访问。而对象数组中的所有元素是一个类的实例或其它数组的引用,和字符串操作一样,不能直接访问 Java 传递给 JNI 层的数组,必须选择合适的 JNI 函数来访问和设置 Java 层的数组对象。
2. 数组访问示例
2.1 基本类型数组
Java 层:
private native double[] sumAndAverage(int[] numbers);
JNI 层:
JNIEXPORT jdoubleArray JNICALL Java_HelloJNI_sumAndAverage(JNIEnv *env, jobject obj, jintArray inJNIArray) {
//类型转换 jintArray -> jint*
jboolean isCopy;
jint* inArray = env->GetIntArrayElements(inJNIArray, &isCopy);
if (JNI_TRUE == isCopy) {
cout << "C 层的数组是 java 层数组的一份拷贝" << endl;
} else {
cout << "C 层的数组指向 java 层的数组" << endl;
}
if(nullptr == inArray) return nullptr;
//获取到数组长度
jsize length = env->GetArrayLength(inJNIArray);
jint sum = 0;
for(int i = 0; i < length; ++i) {
sum += inArray[i];
}
jdouble average = (jdouble)sum / length;
//释放数组
env->ReleaseIntArrayElements(inJNIArray, inArray, 0); // release resource
//构造返回数据,outArray 是指针类型,需要 free 或者 delete 吗?要的
jdouble outArray[] = {sum, average};
jdoubleArray outJNIArray = env->NewDoubleArray(2);
if(NULL == outJNIArray) return NULL;
//向 jdoubleArray 写入数据
env->SetDoubleArrayRegion(outJNIArray, 0, 2, outArray);
return outJNIArray;
}
2.2 引用类型数组
Java 层:
public native String[] operateStringArrray(String[] array);
JNI 层:
JNIEXPORT jobjectArray JNICALL Java_com_xxx_jni_JNIArrayManager_operateStringArrray
(JNIEnv * env, jobject object, jobjectArray objectArray_in)
{
//获取到长度信息
jsize size = env->GetArrayLength(objectArray_in);
/*******获取从JNI传过来的String数组数据**********/
for(int i = 0; i < size; i++)
{
jstring string_in= (jstring)env->GetObjectArrayElement(objectArray_in, i);
char *char_in = env->GetStringUTFChars(str, nullptr);
}
/***********从JNI返回String数组给Java层**************/
jclass clazz = env->FindClass("java/lang/String");
jobjectArray objectArray_out;
const int len_out = 5;
objectArray_out = env->NewObjectArray(len_out, clazz, NULL);
char * char_out[]= { "Hello,", "world!", "JNI", "is", "fun" };
jstring temp_string;
for( int i= 0; i < len_out; i++ )
{
temp_string = env->NewStringUTF(char_out[i]);
env->SetObjectArrayElement(objectArray_out, i, temp_string);
}
return objectArray_out;
}
2.3 二维数组
Java 层:
public native int[][] operateTwoIntDimArray(int[][] array_in);
JNI 层:
JNIEXPORT jobjectArray JNICALL Java_com_xxx_jni_JNIArrayManager_operateTwoIntDimArray(JNIEnv * env, jobject object, jobjectArray objectArray_in)
{
/********** 解析从Java得到的int型二维数组 **********/
int i, j ;
const int row = env->GetArrayLength(objectArray_in);//获取二维数组的行数
jarray array = (jarray)env->GetObjectArrayElement(objectArray_in, 0);
const int col = env->GetArrayLength(array);//获取二维数组每行的列数
//根据行数和列数创建int型二维数组
jint intDimArrayIn[row][col];
for(i =0; i < row; i++)
{
array = (jintArray)env->GetObjectArrayElement(objectArray_in, i);
//操作方式一,这种方法会申请natvie memory内存
jint *coldata = env->GetIntArrayElements((jintArray)array, NULL );
for (j=0; j<col; j++) {
intDimArrayIn [i] [j] = coldata[j]; //取出JAVA类中int二维数组的数据,并赋值给JNI中的数组
}
//操作方式二,赋值,这种方法不会申请内存
// env->GetIntArrayRegion((jintArray)array, 0, col, (jint*)&intDimArrayIn[i]);
env->ReleaseIntArrayElements((jintArray)array, coldata,0 );
}
/**************创建一个int型二维数组返回给Java**************/
const int row_out = 2;//行数
const int col_out = 2;//列数
//获取数组的class
jclass clazz = env->FindClass("[I");//一维数组的类
//新建object数组,里面是int[]
jobjectArray intDimArrayOut = env->NewObjectArray(row_out, clazz, NULL);
int tmp_array[row_out][col_out] = {{0,1},{2,3}};
for(i = 0; i< row_out; i ++)
{
jintArray intArray = env->NewIntArray(col_out);
env->SetIntArrayRegion(intArray, 0, col_out, (jint*)&tmp_array[i]);
env->SetObjectArrayElement(intDimArrayOut, i, intArray);
}
return intDimArrayOut;
}
3. JNI 字符串处理函数
GetArrayLength
jsize (GetArrayLength)(JNIEnv env, jarray array);
返回数组中的元素个数
NewObjectArray
jobjectArray NewObjectArray (JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);
构建 JNI 引用类型的数组,它将保存类 elementClass 中的对象。所有元素初始值均设为 initialElement,一般使用 NULL 就好。如果系统内存不足,则抛出 OutOfMemoryError 异常
GetObjectArrayElement和SetObjectArrayElement
jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
返回 jobjectArray 数组的元素,通常是获取 JNI 引用类型数组元素。如果 index 不是数组中的有效下标,则抛出 ArrayIndexOutOfBoundsException 异常。
void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject value)
设置 jobjectArray 数组中 index 下标对象的值。如果 index 不是数组中的有效下标,则会抛出 ArrayIndexOutOfBoundsException 异常。如果 value 的类不是数组元素类的子类,则抛出 ArrayStoreException 异常。
New\Array 函数集
NativeTypeArray New<PrimitiveType>Array (JNIEnv* env, jsize size)
用于构造 JNI 基本类型数组对象。
在实际应用中把 PrimitiveType 替换为某个实际的基本类型数据类型,然后再将 NativeType 替换成对应的 JNI Native Type 即可,具体的:
函数名 返回类型
NewBooleanArray() jbooleanArray
NewByteArray() jbyteArray
NewCharArray() jcharArray
NewShortArray() jshorArray
NewIntArray() jintArray
NewLongArray() jlongArray
NewFloatArray() jfloatArray
NewDoubleArray() jdoubleArray
Get/ReleaseArrayElements函数集
NativeType* Get<PrimitiveType>ArrayElements(JNIEnv *env, NativeTypeArray array, jboolean *isCopy)
该函数用于将 JNI 数组类型转换为 JNI 基本数据类型数组,在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将NativeType替换成对应的 JNI Native Type 即可:
函数名 转换前类型 转换后类型
GetBooleanArrayElements() jbooleanArray jboolean*
GetByteArrayElements() jbyteArray jbyte*
GetCharArrayElements() jcharArray jchar*
GetShortArrayElements() jshortArray jshort*
GetIntArrayElements() jintArray jint*
GetLongArrayElements() jlongArray jlong*
GetFloatArrayElements() jfloatArray jfloat*
GetDoubleArrayElements() jdoubleArray jdouble*
void Release<PrimitiveType>ArrayElements (JNIEnv *env, NativeTypeArray array, NativeType *elems,jint mode);
该函数用于通知 JVM,数组不再使用,可以清理先关内存了。在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将 NativeType 替换成对应的 JNI Native Type 即可:
函数名 NativeTypeArray NativeType
ReleaseBooleanArrayElements() jbooleanArray jboolean
ReleaseByteArrayElements() jbyteArray jbyte
ReleaseCharArrayElements() jcharArray jchar
ReleaseShortArrayElements() jshortArray jshort
ReleaseIntArrayElements() jintArray jint
ReleaseLongArrayElements() jlongArray jlong
ReleaseFloatArrayElements() jfloatArray jfloat
ReleaseDoubleArrayElements() jdoubleArray jdouble
Get/Set\ArrayRegion
void Set<PrimitiveType>ArrayRegion (JNIEnv *env, NativeTypeArray array, jsize start, jsize len, NativeType *buf);
该函数用于将基本类型数组某一区域复制到 JNI 数组类型中。在实际使用过程中将 PrimitiveType 替换成某个实际的基本类型元素访问函数,然后再将 NativeType 替换成对应的 JNI Native Type 即可:
函数名 NativeTypeArray NativeType
SetBooleanArrayRegion() jbooleanArray jboolean
SetByteArrayRegion() jbyteArray jbyte
SetCharArrayRegion() jcharArray jchar
SetShortArrayRegion() jshortArray jshort
SetIntArrayRegion() jintArray jint
SetLongArrayRegion() jlongArray jlong
SetFloatArrayRegion() jfloatArray jfloat
SetDoubleArrayRegion() jdoubleArray jdouble
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20402,转载请注明出处。
评论0