在我的本机C ++代码中,有一个必须返回Java对象的函数。使用JNI从Java代码中调用此函数。在返回的对象内部,有一个二维双数组字段,必须在返回对象之前填充。虽然有关于在jobject中设置数组字段的示例代码,但是没有明确的方法来设置多维数组字段,无论它们是基元数组还是其他对象。一个人到底是怎么做到的?
答案 0 :(得分:2)
经过一番研究,我发现诀窍是将多维数组字段视为一个jobjects数组。在这个例子中,这些jobject实际上是双精度数组。这可以根据需要继续进行多个维度。包含有问题的多维数组字段的对象是:
package com.example;
public class ObjectTransform{
public String name;
public double[][] transform;
public ObjectTransform(){
name = "";
transform = new double[4][4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
transform[i][j] = i == j ? 1 : 0;
}
}
其中多维数组实际上是4乘4变换矩阵。为了证明拥有包含数组的对象的必要性,还有另一个String字段。有了这个,返回ObjectTransform
的本机C ++函数如下:
extern "C" JNIEXPORT jobject JNICALL Java_com_example_examplefunction(
JNIEnv* env, jclass* class_){
//Get class identifier of our object
jclass cls = env->FindClass("com/example/ObjectTransform");
//Get constructor identifier for our object
jmethodID constructor = env->GetMethodID(cls,"<init>","()V");
//Get field identifiers of our object
//Transform is a two dimensional double array, denoted as [[D
jfieldID nameID = env->GetFieldID(cls,"name","Ljava/lang/String;");
jfieldID transformID = env->GetFieldID(cls,"transform","[[D");
//Allocate object that we will return
jobject jresult = env->NewObject(cls, constructor);
//Set object name
env->SetObjectField(jresult, nameID, env->NewStringUTF("some name"));
/*
* Build object transform matrix
*/
//Get rows of the matrix in JVM heap space, we will change them
jobjectArray rows = reinterpret_cast<jobjectArray>(
env->GetObjectField(jresult,transformID));
//Allocate some temporary variables
jdoubleArray jrow;
jdouble row[4];
//Traverse rows
for(int j=0;j<4;j++){
//Traverse columns
for(int k=0;k<4;k++){
//Set current element of the matrix accordingly
row[k] = calculate_some_value(j,k);
}
//Temporarily allocate a new row in JVM heap space
//No need to unpin an array allocated with New...Array in the end
jrow = env->NewDoubleArray(4);
//Fill the newly allocated row
env->SetDoubleArrayRegion(jrow,0,4,row);
//Write the newly filled row to the appropriate row of our matrix
env->SetObjectArrayElement(rows,j,jrow);
}
return jresult;
}
可以像往常一样使用以下签名从Java内部调用本机函数:
package com.example;
...
private native ObjectTransform examplefunction();
从这里开始,设置任意对象的多维数组字段的过程非常简单:代替[[D
,编写[[com.example.exampleclass;
。而不是NewDoubleArray
,请致电NewObjectArray
。而不是SetDoubleArrayRegion
,而是将对象数组的所有元素分别按SetObjectArrayElement
设置为您事先创建的对象。
对此代码的所有改进当然都是受欢迎的。