2016-05-18 16 views
0

Ich habe folgenden Code zu Array of Object Array mit Strukturelementen von primitiven Typen, ich kann nicht, um primitive Typen in Jobject zu konvertieren, zurückgegeben und dann auf ObjectArray gesetzt SetObjectArrayElement Methode,JNI: Primitive Typ in Jobject konvertieren oder SetObjectArrayElement des Objekttyps nach dem Casting

Hier ist meine C-Struktur 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]; }; 

Mein 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;  } 

Die Fehler ich habe ist

A fatal error has been detected by the Java Runtime Environment: 

SIGSEGV (0xb) bei 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) Problematische Rahmen: V [libjvm.so + 0x2a80e5] jni_SetObjectArrayElement + 0x1c5

fehlgeschlagen Coredump zu schreiben. Core Dumps wurden deaktiviert. So aktiviert Kern Dumping, versuchen „ulimit -c unlimited“ vor dem Start Java wieder

Eine Fehlerbericht-Datei mit weiteren Informationen wird gespeichert als: /DATA1/home/user1/Myname/myproject/hs_err_pid4754.log

wenn Sie möchten, einen Fehlerbericht einreichen, besuchen Sie bitte: http://bugreport.sun.com/bugreport/crash.jsp

Meine Fragen sind

  1. Kann ich Array von Object Array zurück wie oben
  2. Wenn ja, wie primitive Art in Job-Objekt zu konvertieren

Was ist falsch mit obigen JNI-Code .... ??? Vielen Dank ...

+0

Es wäre viel einfacher, eine Java 'CheqDtl'-Klasse mit Feldern wie' long irno' und 'String bank_accno1' zu erstellen, dieses Objekt an Ihren JNI-Aufruf zu übergeben und einfach die Felder in diesem einen Objekt auszufüllen: 'geschütztes statisches natives Void FillCheqDtl (CheqDtl dtl); ... CheqDtl dtl = neues CheqDtl(); FillCheqDtl (dtl); ... 'Siehe http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16536 –

+0

Ich habe mit dem Erstellen der Klasse getan, dann füllen Sie es aus Wert, ich möchte nur versuchen, wie dies ohne Klasse ... ty –

Antwort

1

Sie können dies nicht erreichen, indem Sie einfach zu jobject konvertieren. C++ hat absolut keine Kenntnis von Java Autoboxing. Sie müssen die entsprechenden Java-Objekte manuell instanziieren.

Zum Beispiel muss irno in die Instanz von Java Long-Klasse (unter der Annahme 64-Bit-Betriebssystem) konvertiert werden. Um dies zu tun, müssen Sie:

  1. Finde Kennung von Long-Klasse mit FindClass
  2. lokalisieren Kennung seines Konstruktor, indem irno als Argument mit GetMethodID
  3. Erstellen Sie neues Java-Langes Objekt langen Urtyp akzeptiert an den Konstruktor mit NewObjectA

Andere Variablen müssen in die entsprechenden Java-Typen umgewandelt werden: C++ Doppel zu java double, C++ char [], um Java-String oder java char [] a Und so weiter.

Wenn Sie eine Menge solcher primitiven Objekte an und von Java weitergeben, dann schlage ich vor, dass Sie eine Serialisierungsbibliothek wie Google Protobuf verwenden. Sie füllen Protobuf-Nachricht in Java, serialisieren es in Byte-Array und übergeben diese Byte-Array in Java. In Java deserialisieren Sie es und erhalten ein nettes Java-Objekt. Wenn Sie weitere Felder hinzufügen müssen, müssen Sie keinen fehleranfälligen JNI-Code mehr schreiben.

+0

@ gudok Ich werde versuchen und lassen Sie wissen ... ty –

+0

Ich bin nicht in der Lage, unsigned long zu konvertieren (jvalue *), in NewObjectA Methode irgendeine Idee ...? falscher Wert auf Java-Seite erhalten ... –

+0

Verwenden Sie NewObject: 'NewObject (env, class_id, constructor_id, cheqdtl-> irno)' – gudok