如何使用JNI传递和接收对象

时间:2013-08-22 12:54:05

标签: java c exception exception-handling java-native-interface

我有一个JAVA应用程序,我希望使用C将对象作为参数传递给JNI代码,并且我想再次从{{1}接收对象使用C将代码添加到JAVA

在JAVA方面,我只创建了一个应用程序并将其传递给方法,如下所示

JNI

此对象传递给类似

的方法
JlibFprint.fp_image_data fpimg = new JlibFprint.fp_image_data();   //object to be pass  
 //fp_image_data is the static inner class of the class JlibFprint

JlibFprint.fp_image_data fpimg1 = new JlibFprint.fp_image_data();   //received object

该方法的JNI代码如下所示:

fpimg1 = JlibFprint.binary_image(fpimg);

但是从JAVA端的这些JNI代码函数返回后,该方法显示了异常,如

JNIEXPORT jobject JNICALL Java_jlibfprint_JlibFprint_binary_1image(JNIEnv *env, jclass jcls,jobject imgobj)
{
    struct fp_img img;
    struct fp_img *imgptr;
    imgptr = &img;
    jfp2cfp(env,imgobj,imgptr);     
    fp_init();
    imgptr = fp_img_binarize(imgptr);
    cfp2jfp(env, imgobj, imgptr);
    fp_exit();
    return imgobj;
}

void jfp2cfp(JNIEnv* env, jobject obj, fp_img *fpd)
{
    /* Determines all the fields of the object */
    jclass fpClass = env->FindClass("jlibfprint/JlibFprint$fp_image_data");
            jfieldID height;
            jfieldID width;
            jfieldID length;
            jfieldID data;
            jbyteArray dataArray;

            height = env->GetFieldID(fpClass, "height", "I");
            width = env->GetFieldID(fpClass, "width", "I");
            length = env->GetFieldID(fpClass, "length", "I");
            data = env->GetFieldID(fpClass, "data", "[B");

         /* Starts to fill fpd */
       fpd->height = env->GetIntField(obj, height);
        fpd->width = env->GetIntField(obj, width);
        fpd->length = env->GetIntField(obj, length);
        printf("\n height :%d",fpd->height);
        printf("\n width  :%d",fpd->width);
        printf("\n length :%d",fpd->length);
        dataArray = static_cast<jbyteArray>(env->GetObjectField(obj, data));
        env->GetByteArrayRegion(dataArray, 0, FP_PRINT_DATA_DATA_SIZE, (jbyte*)fpd->data);

}

void cfp2jfp(JNIEnv* env, jobject obj, fp_img* fpd)
{
    /* Determines all the fields of the object */
    jclass fpClass = env->FindClass("jlibfprint/JlibFprint$fp_image_data");
        jfieldID height;
        jfieldID width;
        jfieldID length;
        jfieldID data;

        jbyteArray dataArray;
        height = env->GetFieldID(fpClass, "height", "I");
        width = env->GetFieldID(fpClass, "width", "I");
        length = env->GetFieldID(fpClass, "length", "I");
        data = env->GetFieldID(fpClass, "data", "[B");

        /* Starts to fill the obj */
        env->SetIntField(obj, height, fpd->height);
        env->SetIntField(obj, width, fpd->width);
        env->SetIntField(obj, length, fpd->length);

        dataArray = env->NewByteArray(FP_PRINT_DATA_DATA_SIZE);
        env->SetByteArrayRegion(dataArray, 0, FP_PRINT_DATA_DATA_SIZE, (jbyte*)fpd->data);

        env->SetObjectField(obj, data, dataArray);
}

即对象没有正确处理,并且它不会从JNI层返回任何内容。 但是我没有得到我应该在JNI代码中更改的内容,以便它将返回正确的对象。

请建议我解决。

1 个答案:

答案 0 :(得分:1)

如果指定的区域超出了数组的边界,GetByteArrayRegion()SetByteArrayRegion()都会抛出ArrayIndexOutOfBoundsException。

您对SetByteArrayRegion()的调用看起来是正确的 - 它会在创建所需大小的数组之后立即生效。

验证GetByteArrayRegion()访​​问的条目数组的大小至少为FP_PRINT_DATA_DATA_SIZE。

顺便说一下,另一种方法是使用GetByteArrayElements()ReleaseByteArrayElements()可以返回指向Java用于数组的相同内存的指针。