简体   繁体   English

JNI:转换后将基本类型转换为Jobject或对象类型的SetObjectArrayElement

[英]JNI : convert Primitive type to jobject Or SetObjectArrayElement of Object type after casting

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, 我有以下代码返回填充有原始类型的struct元素的Object Array,我不知道如何将原始类型转换为jobject,然后使用SetObjectArrayElement方法设置为ObjectArray,

Here is my C struct info 这是我的C结构信息

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 我的JNI代码

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 SIGSEGV(0xb),位于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 JRE版本:7.0_09-b05 Java VM:Java HotSpot(TM)客户端VM(23.5-b02混合模式linux-x86)问题框架: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 要启用核心转储,请在再次启动Java之前尝试“ ulimit -c unlimited”

An error report file with more information is saved as: /DATA1/home/user1/Myname/myproject/hs_err_pid4754.log 包含更多信息的错误报告文件将另存为:/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 如果您想提交错误报告,请访问: http : //bugreport.sun.com/bugreport/crash.jsp

My questions are 我的问题是

  1. Can I return Array Of Object array like above 我可以像上面一样返回对象数组
  2. If yes how to convert primitive type to jobject 如果是,如何将原始类型转换为Jobject

What is wrong with above JNI code ....??? 上面的JNI代码有什么问题.... ??? Thank you... 谢谢...

You can't achieve this by simply converting to jobject . 您不能仅通过转换为jobject C++ has absolutely no knowledge of java autoboxing. C ++完全不了解Java自动装箱。 You will need to instantiate appropriate java objects manually. 您将需要手动实例化适当的java对象。

For example, irno needs to be converted to instance of java Long class (assuming 64-bit OS). 例如, irno需要转换为java Long类的实例(假设使用64位OS)。 In order to do so, you need: 为此,您需要:

  1. Locate identifier of Long class with FindClass 使用FindClass找到Long类的标识符
  2. Locate identifier of its constructor which accepts primitive type long with GetMethodID 找到其构造函数的标识符,该构造函数长时间使用GetMethodID接受原始类型
  3. Create new java Long object by passing irno as argument to its constructor with NewObjectA 通过使用NewObjectAirno作为参数传递给其构造函数来创建新的Java Long对象

Other 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. 其他变量必须转换为它们相应的Java类型:c ++ double到java Double,c ++ char []到java String或java char [],依此类推。

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. 如果您要在Java和Java之间传递大量此类原始对象,那么建议您使用一些序列化库,例如google protobuf。 You fill in protobuf message in java, serialize it into byte array and pass this byte array into java. 您用Java填写protobuf消息,将其序列化为字节数组,然后将此字节数组传递给Java。 In java, you deserialize it and get nice java object. 在Java中,您可以反序列化它并获得漂亮的Java对象。 When you need to add more fields, then you won't need to write any more error-prone JNI code. 当您需要添加更多字段时,则无需再编写任何容易出错的JNI代码。

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

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