2013-08-22 42 views
3

如何传递和接收对象我在一个JAVA应用程序,我要传递的对象作为参数传递给C代码中使用JNI,我想再次使用JNI接收来自C代码的对象JAVA使用JNI

在JAVA侧我已经简单地创建的应用程序,并如图所示波纹管

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 

这个目的是通过该方法等

fpimg1 = JlibFprint.binary_image(fpimg); 

而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代码a吨的JAVA侧的方法示出了像

java.lang.ArrayIndexOutOfBoundsException 
    at jlibfprint.JlibFprint.binary_image(Native Method) 
    at jlibfprint.SampleRun.main(SampleRun.java:96) 

即对象未正确地处理该异常和它不会从JNI层返回任何东西。 但我没有得到什么,我应该改变在JNI代码,以便它会返回正确的对象。

请给我任何解决方案。

+0

另请参阅:https://stackoverflow.com/questions/5231599/is-there-any-way-to-pass-a-java-array-to-c-through-jni-without-making-a-副本 – Trilarion

回答

1

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

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

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

顺便说,一个替代方案是使用GetByteArrayElements()ReleaseByteArrayElements(),其可以的指针返回到相同的存储器Java使用的阵列。

+0

谢谢。请给我解释一下这个例子,我应该用什么替换SetByteArrayRegion()' – rachana

+0

我没有看到任何不正确的调用SetByteArrayRegion()。我的第一步是验证传递给GetByteArrayRegion()的数组的长度至少为FP_PRINT_DATA_SIZE。在你完成这个工作之后,如果你认为试图避免复制数组很有用,下面是GetByteArrayElements/ReleaseByteArrayElements()的一些细节 - http://stackoverflow.com/questions/8439233/how-to-convert-jbytearray- to-native-char-in-jni。 –

+0

我已经设置FP_PRINT_DATA_SIZE的值是327680,并且它与输入数组的大小相当不够 – rachana