I'm have following code to return Array of Object Array filled with struct elements of primitive types , I don't know how to convert primitive types to jobject, and then set to ObjectArray using SetObjectArrayElement method,
Here is my C struct info
struct cheqdtl {
unsigned long irno;
char bank_accno1 [16];
unsigned long bank_id;
unsigned long outlet_id;
char bank_accno [16];
char cheque_num [41];
double deposit_amt;
char chq_date [4]; };
My JNI code
JNIEXPORT jobjectArray JNICALL Java_nativeclass_Jmain_getChequeList (JNIEnv *env,jobject jobj,jint ch,jstring benAccNo,jstring fromDate,jstring toDate){
clientlist *cl = new clientlist();
ShortInt lcount = 0;
int i;
jmp_buf jmpb;
const char *ben_acc_no = env->GetStringUTFChars(benAccNo, NULL);
const char *from_date = env->GetStringUTFChars(fromDate, NULL);
const char *to_date = env->GetStringUTFChars(toDate, NULL);
struct b_date f_date, t_date;
char temp_date[10];
mov_mem((char *)from_date, temp_date, 2);
temp_date[2] = '\0';
f_date.day = atoi(temp_date);
mov_mem((char *)from_date + 3, temp_date, 2);
temp_date[2] = '\0';
f_date.month = atoi(temp_date);
mov_mem((char *)from_date+6, temp_date, 4);
temp_date[4] = '\0';
f_date.year = atoi(temp_date);
mov_mem((char *)to_date, temp_date, 2);
temp_date[2] = '\0';
t_date.year = atoi(temp_date);
mov_mem((char *)to_date + 3, temp_date, 2);
temp_date[2] = '\0';
t_date.month = atoi(temp_date);
mov_mem((char *)to_date + 6, temp_date, 4);
temp_date[4] = '\0';
t_date.year = atoi(temp_date);
struct cheqdtl *cq_dtl = NULL;
cq_dtl = (struct cheqdtl *)malloc( sizeof( struct cheqdtl) );
cl->get_cheque_list((int)ch,(char *)ben_acc_no, &f_date, &t_date, &cq_dtl, &lcount);
jclass objCls= env->FindClass("java/lang/Object");
if( objCls == NULL )
return NULL;
jobjectArray outObjArr = env->NewObjectArray( lcount, objCls, NULL );
jmethodID jobjConstrId = env->GetMethodID( objCls, "<init>", "()V" );
if( jobjConstrId == 0)
return NULL;
jobjectArray rowObjArr ;
if( !lcount )
return NULL;
for( i = 0; i < lcount; ++i ) {
rowObjArr = env->NewObjectArray(8, objCls, NULL);
cout<<"\n Get Array Length:- "<<env->GetArrayLength(rowObjArr)<<endl;
std::cout<<cq_dtl[i].irno<<"\n";
std::cout<<cq_dtl[i].bank_accno1<<"\n";
std::cout<<cq_dtl[i].bank_id<<"\n";
std::cout<<cq_dtl[i].outlet_id<<"\n";
std::cout<<cq_dtl[i].bank_accno<<"\n";
std::cout<<cq_dtl[i].cheque_num<<"\n";
std::cout<<cq_dtl[i].deposit_amt<<"\n";
std::cout<<cq_dtl[i].chq_date<<"\n";
env->SetObjectArrayElement(rowObjArr, 0, (jobject) cq_dtl[i].irno);
env->SetObjectArrayElement(rowObjArr, 1, (jobject) cq_dtl[i].bank_accno1);
env->SetObjectArrayElement(rowObjArr, 2, (jobject) cq_dtl[i].bank_id);
env->SetObjectArrayElement(rowObjArr, 3, (jobject) cq_dtl[i].outlet_id);
env->SetObjectArrayElement(rowObjArr, 4, (jobject) cq_dtl[i].bank_accno);
env->SetObjectArrayElement(rowObjArr, 5, (jobject) cq_dtl[i].cheque_num);
env->SetObjectArrayElement(rowObjArr, 6, (jobject) cq_dtl[i].deposit_amt);
env->SetObjectArrayElement(rowObjArr, 7, (jobject) cq_dtl[i].chq_date);
if( rowObjArr )
env->SetObjectArrayElement( outObjArr, i, rowObjArr );
env->DeleteLocalRef( rowObjArr );
}
env->DeleteLocalRef( objCls );
free( cq_dtl );
delete cl;
return outObjArr; }
The Error I got is
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x010290e5, pid=4754, tid=4152195952
JRE version: 7.0_09-b05 Java VM: Java HotSpot(TM) Client VM (23.5-b02 mixed mode linux-x86 ) Problematic frame: V [libjvm.so+0x2a80e5] jni_SetObjectArrayElement+0x1c5
Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
An error report file with more information is saved as: /DATA1/home/user1/Myname/myproject/hs_err_pid4754.log
If you would like to submit a bug report, please visit: http://bugreport.sun.com/bugreport/crash.jsp
My questions are
What is wrong with above JNI code ....??? Thank you...
You can't achieve this by simply converting to jobject
. C++ has absolutely no knowledge of java autoboxing. You will need to instantiate appropriate java objects manually.
For example, irno
needs to be converted to instance of java Long class (assuming 64-bit OS). In order to do so, you need:
irno
as argument to its constructor with NewObjectAOther variables must be converted to their corresponding java types: c++ double to java Double, c++ char[] to java String or to java char[] and so on.
If you are going to pass a lot of such primitive objects to and from java, then I suggest that you use some serialization library, such as google protobuf. You fill in protobuf message in java, serialize it into byte array and pass this byte array into java. In java, you deserialize it and get nice java object. When you need to add more fields, then you won't need to write any more error-prone JNI code.