繁体   English   中英

如何通过JNI设置Java对象的多维数组字段

[英]How to set multidimensional array field of Java object through JNI

在我的本机C ++代码中,有一个必须返回Java对象的函数。 使用JNI在Java代码中调用此函数。 在返回的对象内部,必须有一个二维双精度数组字段,该字段必须在返回对象之前被填充。 尽管有一些示例代码涉及在jobject内设置数组字段,但没有明确的方法来设置多维数组字段,无论它们是图元数组还是其他对象。 如何才能做到这一点?

经过研究后,我发现诀窍是将多维数组字段视为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 x 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分别将对象数组的所有元素设置为您事先创建的对象。

当然,欢迎对此代码进行所有改进。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM