JNI 中创建对象数组

JNI 中创建对象数组

在上一篇中介绍了JNI中创建对象。本文是JNI系列的第十篇,介绍JNI中的如何调在Native代码中创建对象数组。

系列文章的大纲如下:

JNI 中创建对象数组

创建对象数组很简单,一个函数就可以了,如下:

// 创建长度为length的类型为elementClass的数组,默认值为initialElement
jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);

从数组中获取元素:

// 获取数组array中的第index个元素
jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index);

更新数组中的元素:

// 将数组array的第index个元素设置为value
void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value);

其他接口详见JNI 数组

通过下面的实例来加深一下理解。

实例

我们来看一个实例。

package myjni;

public class JNIObjectArray {
    static {
        System.loadLibrary("hello");
    }

    // Returns sum and average
    private native Double[] sumAndAverage(Integer[] numbers);

    public static void main(String[] args) {
        JNIObjectArray obj = new JNIObjectArray();
        Integer[] numbers = {2, 4, 5};
        Double[] results = obj.sumAndAverage(numbers);
        System.out.println("In Java, the sum is " + results[0]);
        System.out.println("In Java, the average is " + results[1]);
    }
}

如果还不清楚如果生成头文件请参考JNI简介

生成头文件myjni_JNIObjectArray.h的签名为:

/*
 * Class:     myjni_JNIObjectArray
 * Method:    sumAndAverage
 * Signature: ([Ljava/lang/Integer;)[Ljava/lang/Double;
 */
JNIEXPORT jobjectArray JNICALL Java_myjni_JNIObjectArray_sumAndAverage
  (JNIEnv *, jobject, jobjectArray);

实现函数Java_myjni_JNIObjectArray_sumAndAverage


JNIEXPORT jobjectArray JNICALL Java_myjni_JNIObjectArray_sumAndAverage(JNIEnv *env, jobject obj, jobjectArray array) {
  jclass classInteger = env->FindClass("java/lang/Integer");
  if (classInteger == nullptr) {
    std::cout << "find class java.lang.Integer failed\n";
    return nullptr;
  }

  jmethodID midIntValue = env->GetMethodID(classInteger, "intValue", "()I");
  if (midIntValue == nullptr) {
    std::cout << "get intValue() failed\n";
    return nullptr;
  }

  jsize length = env->GetArrayLength(array);
  jint sum = 0;
  for (int i = 0; i < length; i++) {
    jobject objInteger = env->GetObjectArrayElement(array, i);
    if (objInteger == nullptr) {
      std::cout << "get " << i << " element in array failed\n";
      return nullptr;
    }
    sum += env->CallIntMethod(objInteger, midIntValue);
  }

  double average = (double)sum / length;
  std::cout << "In C++, the sum is " << sum << "\n";
  std::cout << "In C++, the average is " << average << "\n";

  jclass classDouble = env->FindClass("java/lang/Double");
  if (classDouble == nullptr) {
    std::cout << "find class java.lang.Double failed\n";
    return nullptr;
  }

  jobjectArray resultArray = env->NewObjectArray(2, classDouble, nullptr);
  if (resultArray == nullptr) {
    std::cout << "create Double[] failed\n";
    return nullptr;
  }

  jmethodID midDoubleInit = env->GetMethodID(classDouble, "<init>", "(D)V");
  if (midDoubleInit == nullptr) {
    std::cout << "get Double.<init> failed\n";
    return nullptr;
  }

  jobject objSum = env->NewObject(classDouble, midDoubleInit, (double)sum);
  jobject objAvg = env->NewObject(classDouble, midDoubleInit, average);

  env->SetObjectArrayElement(resultArray, 0, objSum);
  env->SetObjectArrayElement(resultArray, 1, objAvg);

  return resultArray;
}

编译生成动态库,并运行Java程序得到输出:

In Java, the sum is 11.0
In Java, the average is 3.6666666666666665
In C++, the sum is 11
In C++, the average is 3.66667

vx搜:极客Furzoom,关注获取第一手资料。

本文完。

上一篇:比赛模拟-乒乓球


下一篇:JNI获取MAC地址