自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

前言

上一篇《JNI之数组简单操作》介绍的是jintArray的使用,今天就介绍对象数组

  1. jarray               (数组)
  2.   jobjectArray         (object数组)
  3.   jbooleanArray       (boolean数组)
  4.   jbyteArray           (byte数组)
  5.   jshortArray         (short数组)
  6.   jintArray           (int数组)
  7.   jlongArray           (long数组)
  8.   jfloatArray         (float数组)      
  9.   jdoubleArray         (double数组)
复制

其实数组的使用都差不多,但jobjectArray看起来较特殊,就单独拎出来。

正文

这里以Integer[]为例哈,顺带复现一下《JNI之访问方法和域》的使用。

Signature(签名)

  1. #java
  2. #签名:([Ljava/lang/Integer;)[Ljava/lang/Integer;
  3. public static native Integer[] native_sortInteger(Integer[] buffer);
复制

如何还对Signature(签名)获取不太理解,推荐在看看《JNI静态注册》。这里还是在之前《动态注册》基础修改。

  1. /**
  2. * 定义Java和JNI函数的绑定表
  3. * 方法数组,分别为:(native方法 , 方法签名 , 函数指针[JNI中需要实现的方法名])
  4. * 通过javac和javap 获取 方法签名
  5. */
  6. JNINativeMethod method_table[] = {
  7. {"native_sortInteger", "([Ljava/lang/Integer;)[Ljava/lang/Integer;", (void *) native_sort_integer},
  8. };
复制

涉及函数

  1. # 查找class引用
  2. jclass     (*FindClass)(JNIEnv*, const char*);
  3. # 获取方法ID
  4. jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
  5. # 同方法ID调用java方法
  6. jint       (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
  7. # 获取域(变量)ID
  8. jfieldID   (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
  9. # 获取域ID对应的值
  10. jint       (*GetIntField)(JNIEnv*, jobject, jfieldID);
  11. # 改变域ID对应的值
  12. void       (*SetIntField)(JNIEnv*, jobject, jfieldID, jint);
  13. # 获取数组长度
  14. jsize       (*GetArrayLength)(JNIEnv*, jarray);
  15. # 获取指定位置的对jobject
  16. jobject     (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
  17. # 改变指定位置的jobject
  18. void       (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
复制

代码片段

下面是native_sort_integer的实现代码。

看起来有点复杂,其实就是两个功能

  1. 计算数组中的sum

  2. 排序

由于这里用的是Integer对象,因此需要find到Integer的类引用,有两种方式获取Integer中的值,一个是通域ID(属性ID)value,另外一个是通过方法ID。

  1. JNIEXPORT jobjectArray
  2. JNICALL native_sort_integer(JNIEnv *env , jclass clazz, jobjectArray integerArray){
  3.   jclass integerClass = env->FindClass("java/lang/Integer");
  4.   if( NULL == integerClass ){
  5.       LOGE("native_printf_integer integerClass(NULL)");
  6.       return NULL;
  7.   }
  8.   //intValue是Java中Integer的方法
  9.   jmethodID intValueMethodID = env->GetMethodID(integerClass, "intValue", "()I");
  10.   if( NULL == intValueMethodID ){
  11.       LOGE("native_printf_integer intValue(NULL)");
  12.       return NULL;
  13.   }
  14.   //value通过Integer的变量
  15.   jfieldID valueFieldID = env->GetFieldID(integerClass, "value", "I");
  16.   if( NULL == valueFieldID ){
  17.       LOGE("native_printf_integer valueFieldID(NULL)");
  18.       return NULL;
  19.   }
  20.   //获取integerArray长度
  21.   jsize length = env->GetArrayLength(integerArray);
  22.   LOGE("native_printf_integer length(%d)", length);
  23.   if (length <= 0) {
  24.       return NULL;
  25.   }
  26.   int i = 0;
  27.   int sum = 0;
  28.   jint array[length];
  29.   for (i = 0; i < length; i++) {
  30.       jobject object = env->GetObjectArrayElement(integerArray, i);
  31.       if( NULL != object){
  32.           // 1. value值通过jmethodID获取[这里注释掉了]
  33.           //sum += env->CallIntMethod(object, intValueMethodID);
  34.           // 2. value值通过jfieldID直接获取
  35.           jint value = env->GetIntField(object, valueFieldID);
  36.           sum += value;
  37.           array[i] = value;
  38.       }
  39.   }
  40.   //打印SUM值
  41.   LOGE("native_printf_integer sum(%d)", sum);
  42.   //从大到小排序
  43.   int j = 0;
  44.   int temp = 0;
  45.   for (i = 0; i < length - 1; i++) {
  46.       for (j = i + 1; j < length; j++) {
  47.           if (array[i] < array[j]) {
  48.               temp = array[i];
  49.               array[i] = array[j];
  50.               array[j] = temp;
  51.           }
  52.       }
  53.   }
  54.   //重新赋值给jobjectArray
  55.   for (j = 0; j < length; j++) {
  56.       jobject object = env->GetObjectArrayElement(integerArray, j);
  57.       if( NULL != object){
  58.           //通过jfieldID
  59.           env->SetIntField(object, valueFieldID, array[j]);
  60.       }
  61.   }
  62.   return integerArray;
  63. }
复制

上面是重新赋值给integerArray,我们也可以重新创建新的jobjectArray。

在上面基础上修改,赋值那部分进行替换即可。

  1. //创建Integer的jobjectArray,并把array赋值给新的对象数组
  2. jobjectArray newIntegerArray = env->NewObjectArray(length, integerClass, NULL);
  3. jobject integerObject = NULL;
  4. for (j = 0; j < length; j++) {
  5. //创建jobject对象
  6.   integerObject = env->AllocObject(integerClass);
  7.   //给jobject赋值
  8.   env->SetIntField(integerObject, valueFieldID, array[j]);
  9.   //创建的jobject赋值到新的数组中
  10.   env->SetObjectArrayElement(newIntegerArray, j, integerObject);
  11. }
  12. //释放局部引用
  13. env->DeleteLocalRef(integerObject);
复制

参考文章

  1. JNI之访问方法和域

  2. NDK中jni.h头文件完整内容

  3. JNI 中创建对象数组

自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

相关文章

自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

暂无评论

none
暂无评论...