本文主要讲述的在C++端,将java通过jni传进来的类型的转换成对应的c++类型。
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++或汇编语言编写的程序和库。
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;
}
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, "" , "([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);
}
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;
}
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;
}