JNI 中创建对象数组
在上一篇中介绍了JNI中创建对象。本文是JNI系列的第十篇,介绍JNI中的如何调在Native代码中创建对象数组。
系列文章的大纲如下:
- JNI 简介
- JNI 基本类型
- JNI String
- JNI 数组
- JNI 实例变量
- JNI 静态变量
- JNI 回调实例方法与静态方法
- JNI 调用Java中的super.method()
- JNI 中创建对象
- JNI 中创建对象数组
- JNI 中局部引用和全局引用
- JNI 动态注册
- 使用Android NDK编译Android的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,关注获取第一手资料。
本文完。