前言
上一篇《》介绍的是jintArray的使用,今天就介绍对象数组。
jarray (数组) jobjectArray (object数组) jbooleanArray (boolean数组) jbyteArray (byte数组) jshortArray (short数组) jintArray (int数组) jlongArray (long数组) jfloatArray (float数组) jdoubleArray (double数组)
其实数组的使用都差不多,但jobjectArray看起来较特殊,就单独拎出来。
正文
这里以Integer[]为例哈,顺带复现一下《》的使用。
Signature(签名)
#java #签名:([Ljava/lang/Integer;)[Ljava/lang/Integer; public static native Integer[] native_sortInteger(Integer[] buffer);
如何还对Signature(签名)获取不太理解,推荐在看看《》。这里还是在之前《》基础修改。
/** * 定义Java和JNI函数的绑定表 * 方法数组,分别为:(native方法 , 方法签名 , 函数指针[JNI中需要实现的方法名]) * 通过javac和javap 获取 方法签名 */ JNINativeMethod method_table[] = { {"native_sortInteger", "([Ljava/lang/Integer;)[Ljava/lang/Integer;", (void *) native_sort_integer}, };
涉及函数
# 查找class引用 jclass (*FindClass)(JNIEnv*, const char*); # 获取方法ID jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); # 同方法ID调用java方法 jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); # 获取域(变量)ID jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); # 获取域ID对应的值 jint (*GetIntField)(JNIEnv*, jobject, jfieldID); # 改变域ID对应的值 void (*SetIntField)(JNIEnv*, jobject, jfieldID, jint); # 获取数组长度 jsize (*GetArrayLength)(JNIEnv*, jarray); # 获取指定位置的对jobject jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); # 改变指定位置的jobject void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
代码片段
下面是native_sort_integer的实现代码。
看起来有点复杂,其实就是两个功能
-
计算数组中的sum
-
排序
由于这里用的是Integer对象,因此需要find到Integer的类引用,有两种方式获取Integer中的值,一个是通域ID(属性ID)value,另外一个是通过方法ID。
JNIEXPORT jobjectArray JNICALL native_sort_integer(JNIEnv *env , jclass clazz, jobjectArray integerArray){ jclass integerClass = env->FindClass("java/lang/Integer"); if( NULL == integerClass ){ LOGE("native_printf_integer integerClass(NULL)"); return NULL; } //intValue是Java中Integer的方法 jmethodID intValueMethodID = env->GetMethodID(integerClass, "intValue", "()I"); if( NULL == intValueMethodID ){ LOGE("native_printf_integer intValue(NULL)"); return NULL; } //value通过Integer的变量 jfieldID valueFieldID = env->GetFieldID(integerClass, "value", "I"); if( NULL == valueFieldID ){ LOGE("native_printf_integer valueFieldID(NULL)"); return NULL; } //获取integerArray长度 jsize length = env->GetArrayLength(integerArray); LOGE("native_printf_integer length(%d)", length); if (length <= 0) { return NULL; } int i = 0; int sum = 0; jint array[length]; for (i = 0; i < length; i++) { jobject object = env->GetObjectArrayElement(integerArray, i); if( NULL != object){ // 1. value值通过jmethodID获取[这里注释掉了] //sum += env->CallIntMethod(object, intValueMethodID); // 2. value值通过jfieldID直接获取 jint value = env->GetIntField(object, valueFieldID); sum += value; array[i] = value; } } //打印SUM值 LOGE("native_printf_integer sum(%d)", sum); //从大到小排序 int j = 0; int temp = 0; for (i = 0; i < length - 1; i++) { for (j = i + 1; j < length; j++) { if (array[i] < array[j]) { temp = array[i]; array[i] = array[j]; array[j] = temp; } } } //重新赋值给jobjectArray for (j = 0; j < length; j++) { jobject object = env->GetObjectArrayElement(integerArray, j); if( NULL != object){ //通过jfieldID env->SetIntField(object, valueFieldID, array[j]); } } return integerArray; }
上面是重新赋值给integerArray,我们也可以重新创建新的jobjectArray。
在上面基础上修改,赋值那部分进行替换即可。
//创建Integer的jobjectArray,并把array赋值给新的对象数组 jobjectArray newIntegerArray = env->NewObjectArray(length, integerClass, NULL); jobject integerObject = NULL; for (j = 0; j < length; j++) { //创建jobject对象 integerObject = env->AllocObject(integerClass); //给jobject赋值 env->SetIntField(integerObject, valueFieldID, array[j]); //创建的jobject赋值到新的数组中 env->SetObjectArrayElement(newIntegerArray, j, integerObject); } //释放局部引用 env->DeleteLocalRef(integerObject);
参考文章
-
《》
-
《》
-
《》
历史上的今天
暂无评论...
随机推荐
史铁生:我与地坛[节选]
现在让我想想,十五年中坚持到这园子来的人都是谁呢?好像只剩了我和一对老人。十五年前,这对老人还只能算是中年夫妇,我则货真价实还是个青年。他们总是在薄暮时分来园中散步,我不大弄得清他们是从哪边的园门进来,一般来说他们是逆时针绕这园子走。男人个子很高,肩宽腿长,走起路来目不斜视,胯以上直至脖颈挺直不...
I-Cache与D-Cache的区别
前言文档中有关于芯片的介绍,其中一部分是最高运行频率2GHz,32KB L1 I-cache和32KB L1 D-cache ,L2 cache 512K。L1 Cache 表示一级缓存和L2 Cache 表示2级缓存是知道的,但是I-Cache和D-Cache就傻傻分不清了。因此参考网上文章...
getMimeTypeFromExtension记录
前言在Android 13的MediaProvider中有涉及到getMimeTypeFromExtension()的使用,主要是获取文件的MimeType属性。记录于此,方便自己差异。下面代码来自MediaProvider正文获取mimeType//获取文件后缀扩展String...
Android 13framework中添加AIDL
前言添加一个Service并让应用调用,类似于获取AudioManager一样。AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);通过getSystemService()获取X...
Android Socket之客户端封装
前言之前记录了Android中Socket的简单使用,也就是对数据的简单收发操作。这简单的对Socket客户端进行封装。记录于此,方便自己查阅。正文主要socket通信很多地方用,比他Tbox啊,我们作为客户端进行绑定通信。隐藏内容!付费阅读后才能查看!¥2 ¥3多个隐藏块只需支付一次付...
一招永久去除WPS推送广告
前言WPS是国内优秀的办公软件,非常好用和优秀,但广告太多太烦人了。是不是弹出一个,让人有点[恶心]。本文参考其网有文章,摘抄于此。PS: 仅仅在Window系统上验证过。正文打开WPS的配置工具(一般是菜单-》WPS Office-》WPS Office 工具-》配置工具)打开后选择...