Java和C++使用JNI进行交互之C++类型转换相关

本文主要讲述的在C++端,将java通过jni传进来的类型的转换成对应的c++类型。

1、JNI是什么

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方

便移植。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行

交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语

言,只要调用约定受支持就可以了。SUN公司发布的Java 本地接口(JNI)提供了将Java与C/C++、汇编等

本地代码集成的方案,该规范使得在 Java 虚拟机内运行的 Java 代码能够与其它编程语言互相操作,包

括创建本地方法、更新Java对象、调用Java方法,引用 Java类,捕捉和抛出异常等,也允许 Java代码调

用 C/C++或汇编语言编写的程序和库。

2、jstring转换成string

string jstring2str(JNIEnv* env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr,mid,strencode);
    jsize alen = env->GetArrayLength(barr);
    if(alen == 0)
    {
        return "";
    }
    jbyte *ba = env->GetByteArrayElements(barr,JNI_FALSE);
    if(alen > 0) {
        rtn = (char*)malloc(alen+1);
        memcpy(rtn,ba,alen);
        rtn[alen]=0;
    }
    env->ReleaseByteArrayElements(barr,ba,0);
    std::string stemp(rtn);
    if (rtn != NULL) {
        free(rtn);
        rtn = NULL;
    }

    return   stemp;
}

3、string转换成就string

jstring str2jstring(JNIEnv* env,const char* pat)
{
    //定义java String类 strClass
    jclass strClass = (env)->FindClass("java/lang/String");
    //获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    //建立byte数组
    jbyteArray bytes = (env)->NewByteArray(strlen(pat));
    //将char* 转换为byte数组
    (env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
    // 设置String, 保存语言类型,用于byte数组转换至String时的参数
    jstring encoding = (env)->NewStringUTF("GB2312");
    //将byte数组转换为java String,并输出
    return (jstring)(env)->NewObject(strClass, ctorID, bytes, encoding);
}

4、jbytearray转换成string

string jByteArrayToString(JNIEnv *env,jbyteArray jarray) {
    if(jarray == NULL) {
        string str;
        return str;
    }
    jbyte *jbytes = env->GetByteArrayElements(jarray, 0);
    jsize  len = env->GetArrayLength(jarray);
    char *chars = new char[len];
    memset(chars,0,len);
    memcpy(chars, jbytes, len);
    //chars[len] = 0;
    env->ReleaseByteArrayElements(jarray, jbytes, 0);
    string str(chars,len);
    //LOGE("str(%d): %s",str.length(),str.c_str());

//    string hexStr = ToHex(str.c_str(),str.length());
//    LOGE("hex(%d): %s",hexStr.length(),hexStr.c_str());
    return str;
}

5、将jobject转换成C++的结构体

c++的结构体定义如下:

typedef struct {        /* time struct */
    time_t time;        /* time (s) expressed by standard time_t */
    double sec;         /* fraction of second under 1 s */
} gtime_t_f;

struct obsd_t_f{        /* observation data record */
    gtime_t_f time;       /* receiver sampling time (GPST) */
    unsigned char sat, rcv; /* satellite/receiver number */
    unsigned char SNR[NFREQ + NEXOBS]; /* signal strength (0.25 dBHz) */
    unsigned char LLI[NFREQ + NEXOBS]; /* loss of lock indicator */
    unsigned char code[NFREQ + NEXOBS]; /* code indicator (CODE_???) */
    double L[NFREQ + NEXOBS]; /* observation data carrier-phase (cycle) */
    double P[NFREQ + NEXOBS]; /* observation data pseudorange (m) */
    float  D[NFREQ + NEXOBS]; /* observation data doppler frequency (Hz) */
	double BUN[NFREQ + NEXOBS]; /* BiasUncertaintyNanos*/
	int State[NFREQ + NEXOBS];
	long RSTUN [NFREQ + NEXOBS];/*  the error estimate (1-sigma) for the received GNSS time, in nanoseconds */    
    double PRUMP [NFREQ + NEXOBS]; /* the pseudorange's rate uncertainty (1-Sigma) in m/s */
    int ADRS [NFREQ + NEXOBS]; /* Accumulated Delta Range' state */
    double ADRUM [NFREQ + NEXOBS]; /* the baseband carrier-to-noise density in dB-Hz. */
    int MPI[NFREQ + NEXOBS]; /*  a value indicating the 'multipath' state of the event */
};

struct obs_t_f{        /* observation data */
    int n, nmax;         /* number of obervation data/allocated */
    struct obsd_t_f *data;       /* observation data records */
};

该结构体比较复杂,转换过程也比较复杂,该结构体内又嵌套了结构体,结构体内又各个类型的指针、数组,如果把这个结构体转换成功了,那其他的结构体基本都可以成功了。

bool jobject2struct(JNIEnv *env, jobject obsobj, obs_t_f *obs)  //将jobject转换成结构体
{
    /*访问 Java 类的字段,大致步骤如下:
        1.获取 Java 对象的类
        2.获取对应字段的 id
        3.获取具体的字段值 */
    jclass clazz, obsdataobj;
    clazz = env->GetObjectClass(obsobj); //通过对象获取这个类。该函数比较简单,唯一注意的是对象不能为NULL,否则获取的class肯定返回也为NULL
    if (0 == clazz) {
        printf("GetObjectClass returned 0\n");
        return false;
    }
    //获取obs结构体的字段ID
    jfieldID nId = env->GetFieldID(clazz, "n", "I"); //获得属性句柄
    jfieldID nmaxId = env->GetFieldID(clazz, "nmax", "I");
    obs->n = env->GetIntField(obsobj, nId);
    obs->nmax = env->GetIntField(obsobj, nmaxId);

    obsd_t_f *pdata = new obsd_t_f[obs->n];
    memset(pdata, 0, sizeof(obsd_t_f));
    obs->data = pdata;

    jfieldID dataId = env->GetFieldID(clazz, "data", "[Lcn/starcart/rtklib/model/ObsData$Data;");   //得到这个对象的data属性  数组,其为 :  [ + 其类型的域描述符   多维数组则是 n个[ +该类型的域描述符
    if(dataId == NULL)
        printf("Android obs, dataId is null.\n");
    //获取obsd结构体的字段ID
    jobject dataarrayobj = (jobject)env->GetObjectField(obsobj, dataId);   取得该属性的具体值
    jobjectArray dataobj = (jobjectArray)dataarrayobj;
    jsize jdataSize = env->GetArrayLength(dataobj); //得到数组的长度
    for (int i = 0; i < jdataSize; ++i) {
        jobject jdataobj = (jobject)env->GetObjectArrayElement(dataobj, i); //得到一个指向原始数据类型内容的指针
        if(jdataobj == NULL) {
            printf("Android obs, jdataobj is null.\n");
            break;
        }
        jclass obsdatacls = env->GetObjectClass(jdataobj);  //得到这个对象
        jfieldID gpstimeId = env->GetFieldID(obsdatacls, "gtime", "Lcn/starcart/rtklib/model/ObsData$GpsTime;");  //引用类型则为 L + 该类型类描述符
        //获取time结构体的字段ID
        jobject gpstimeobj = (jobject)env->GetObjectField(jdataobj, gpstimeId);
        jclass gpstimecls = env->GetObjectClass(gpstimeobj);
        jfieldID timeId = env->GetFieldID(gpstimecls, "time", "J");
        jfieldID secId = env->GetFieldID(gpstimecls, "sec", "D");
        //----------------------------------time字段ID获取完毕
        jfieldID satId = env->GetFieldID(obsdatacls, "sat", "I");
        jfieldID rcvId = env->GetFieldID(obsdatacls, "rcv", "I");
        jfieldID SNRId = env->GetFieldID(obsdatacls, "SNR", "[I");
        jfieldID LLIId = env->GetFieldID(obsdatacls, "LLI", "[I");
        jfieldID codeId = env->GetFieldID(obsdatacls, "code", "[I");
        jfieldID LId = env->GetFieldID(obsdatacls, "L", "[D");
        jfieldID PId = env->GetFieldID(obsdatacls, "P", "[D");
        jfieldID DId = env->GetFieldID(obsdatacls, "D", "[F");
		jfieldID BUNId = env->GetFieldID(obsdatacls, "BUN", "[D");
        jfieldID StateId = env->GetFieldID(obsdatacls, "State", "[I");
		jfieldID RSTUNId = env->GetFieldID(obsdatacls, "RSTUN", "[J");
		jfieldID PRUMPId = env->GetFieldID(obsdatacls, "PRUMP", "[D");
        jfieldID ADRSId = env->GetFieldID(obsdatacls, "ADRS", "[I");
        jfieldID ADRUMId = env->GetFieldID(obsdatacls, "ADRUM", "[D");
        jfieldID MPIId = env->GetFieldID(obsdatacls, "MPI", "[I");
        //---------------------------------end bsd结构体的字段ID获取完毕
        //把字段Id设置到结构体中
        (obs->data+i)->time.time = env->GetLongField(gpstimeobj, timeId);
        (obs->data+i)->time.sec = env->GetDoubleField(gpstimeobj, secId);
        (obs->data+i)->sat = env->GetIntField(jdataobj, satId);
        (obs->data+i)->rcv = env->GetIntField(jdataobj, rcvId);

        jintArray jSNRarray = (jintArray)env->GetObjectField(jdataobj, SNRId);
        int* SNRarray = env->GetIntArrayElements(jSNRarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jSNRSize = env->GetArrayLength(jSNRarray); //得到数组的长度
        memcpy((obs->data+i)->SNR, SNRarray, jSNRSize);
        env->ReleaseIntArrayElements(jSNRarray, SNRarray, 0); //一但进行绑定就必须进行释放

        jintArray jLLIarray = (jintArray)env->GetObjectField(jdataobj, LLIId);
        int* LLIarray = env->GetIntArrayElements(jLLIarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jLLISize = env->GetArrayLength(jLLIarray); //得到数组的长度
        memcpy((obs->data+i)->LLI, LLIarray, jLLISize);
        env->ReleaseIntArrayElements(jLLIarray, LLIarray, 0); //一但进行绑定就必须进行释放

        jintArray jcodearray = (jintArray)env->GetObjectField(jdataobj, codeId);
        int* codearray = env->GetIntArrayElements(jcodearray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jcodeSize = env->GetArrayLength(jcodearray); //得到数组的长度
        memcpy((obs->data+i)->code, codearray, jcodeSize);
        env->ReleaseIntArrayElements(jcodearray, codearray, 0); //一但进行绑定就必须进行释放

        jdoubleArray jLarray = (jdoubleArray)env->GetObjectField(jdataobj, LId);
        double* Larray = env->GetDoubleArrayElements(jLarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jLSize = env->GetArrayLength(jLarray); //得到数组的长度
        for (int j = 0; j < jLSize; ++j) {
            (obs->data+i)->L[j] = Larray[j];
        }
        env->ReleaseDoubleArrayElements(jLarray, Larray, 0); //一但进行绑定就必须进行释放

        jdoubleArray jParray = (jdoubleArray)env->GetObjectField(jdataobj, PId);
        double* Parray = env->GetDoubleArrayElements(jParray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jPSize = env->GetArrayLength(jParray); //得到数组的长度
        //memcpy((obs->data+i)->P, Parray, jPSize);
        for (int j = 0; j < jPSize; ++j) {
            (obs->data+i)->P[j] = Parray[j];
        }
        env->ReleaseDoubleArrayElements(jParray, Parray, 0); //一但进行绑定就必须进行释放

        jfloatArray jDarray = (jfloatArray)env->GetObjectField(jdataobj, DId);
        float* Darray = env->GetFloatArrayElements(jDarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jDSize = env->GetArrayLength(jDarray); //得到数组的长度
        //memcpy((obs->data+i)->D, Darray, jDSize);
        for (int j = 0; j < jDSize; ++j) {
            (obs->data+i)->D[j] = Darray[j];
        }
        env->ReleaseFloatArrayElements(jDarray, Darray, 0); //一但进行绑定就必须进行释放

		jdoubleArray jBUNarray = (jdoubleArray)env->GetObjectField(jdataobj, BUNId);
        double* BUNarray = env->GetDoubleArrayElements(jBUNarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jBUNSize = env->GetArrayLength(jBUNarray); //得到数组的长度
        for (int j = 0; j < jBUNSize; ++j) {
            (obs->data+i)->BUN[j] = BUNarray[j];
        }
        env->ReleaseDoubleArrayElements(jBUNarray, BUNarray, 0); //一但进行绑定就必须进行释放
		
		jintArray jStatearray = (jintArray)env->GetObjectField(jdataobj, StateId);
        int* Statearray = env->GetIntArrayElements(jStatearray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jStateSize = env->GetArrayLength(jStatearray); //得到数组的长度
        memcpy((obs->data+i)->State, Statearray, jStateSize);
        env->ReleaseIntArrayElements(jStatearray, Statearray, 0); //一但进行绑定就必须进行释放
		
		jlongArray jRSTUNarray = (jlongArray) env->GetObjectField(jdataobj, RSTUNId);
		jlong* RSTUNarray = env->GetLongArrayElements(jRSTUNarray, NULL); //得到一个指向原始数据类型内容的指针
		jsize jRSTUNSize = env->GetArrayLength(jRSTUNarray); //得到数组的长度
		for (int j = 0; j < jRSTUNSize; ++j) {
			(obs->data+i)->RSTUN[j] = RSTUNarray[j];
		}
		env->ReleaseLongArrayElements(jRSTUNarray, RSTUNarray, 0); //一但进行绑定就必须进行释放

		jdoubleArray jPRUMParray = (jdoubleArray)env->GetObjectField(jdataobj, PRUMPId);
        double* PRUMParray = env->GetDoubleArrayElements(jPRUMParray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jPRUMPSize = env->GetArrayLength(jPRUMParray); //得到数组的长度
        memcpy((obs->data+i)->PRUMP, PRUMParray, jPSize);
        env->ReleaseDoubleArrayElements(jPRUMParray, PRUMParray, 0); //
		
		jintArray jADRSarray = (jintArray)env->GetObjectField(jdataobj, ADRSId);
        int* ADRSarray = env->GetIntArrayElements(jADRSarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jADRSSize = env->GetArrayLength(jADRSarray); //得到数组的长度
        memcpy((obs->data+i)->ADRS, ADRSarray, jADRSSize);
        env->ReleaseIntArrayElements(jADRSarray, ADRSarray, 0); //一但进行绑定就必须进行释放
		
        jdoubleArray jADRUMarray = (jdoubleArray)env->GetObjectField(jdataobj, ADRUMId);
        double* ADRUMarray = env->GetDoubleArrayElements(jADRUMarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jADRUMSize = env->GetArrayLength(jADRUMarray); //得到数组的长度
        memcpy((obs->data+i)->ADRUM, ADRUMarray, jADRUMSize);
        env->ReleaseDoubleArrayElements(jADRUMarray, ADRUMarray, 0); //一但进行绑定就必须进行释放

        jintArray jMPIarray = (jintArray)env->GetObjectField(jdataobj, MPIId);
        int* MPIarray = env->GetIntArrayElements(jMPIarray, NULL); //得到一个指向原始数据类型内容的指针
        jsize jMPISize = env->GetArrayLength(jMPIarray); //得到数组的长度
        memcpy((obs->data+i)->MPI, MPIarray, jMPISize);
        env->ReleaseIntArrayElements(jMPIarray, MPIarray, 0); //一但进行绑定就必须进行释放
    }

    for(int i=0;i<obs->n;i++){
        printf("gnssobs (%2d) time= %ld %f   sat=%2d rcv=%d D= %f L= %f P= %f SNR= %f ADRUM=%f RSTUN=%ld PRUMP=%f ADRS=%d MPI=%d\n",
             i,pdata->time.time,pdata->time.sec,pdata->sat,pdata->rcv, pdata->D[0],pdata->L[0],pdata->P[0], pdata->SNR[0]*0.25, pdata->ADRUM[0],
             pdata->RSTUN[0], pdata->PRUMP[0], pdata->ADRS[0], pdata->MPI[0]);
        pdata++;
    }
    return true;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值