};
java中没有结构体的概念,对于结构体你可以建立一个class与其对应,但是转化过程必须自己写。
例如你的结构体为fileinfo,那么你就可以建立一个FileInfo类对应他,但是在C中必须自己转化,也就是传入一个FileInfo的对象,然后对FileInfo对象的属性通过fileinfo结构体逐一复制。
又或者你不建立class与其对应,多建立几个String类型来接受结构体中的各个信息也可以。
但是java是不支持char *这种形式的字符串的,所以你必须把C中字符串表示方式转换成java的String,java中String类型在c中表示形式其实就是jstring类型,它本身是一个复杂类型(jobject类型),实际为执行内存的指针。
对于如何把char*转变成jstring,你可以查看jni相关文档,jni有很多内置函数实现这些功能。
对于复杂类型的转换,如结构体转换成jobject,需要自己手动转换。java不直接支持结构体特性,因为java的jni不是仅仅去支持C的。
////////////////
//通过GetObjectClass方法得到这个对象
jclass objectClass = (env)->GetObjectClass(obj);
//通过GetFieldID方法得到这个对象的fsize属性
jfieldID fs = (env)->GetFieldID(objectClass,"filesize","I");
//再通过SetIntField()方法把这个属性和结构体一一对应赋值对吗?类似于下面这样:
(env)->SetIntField(obj,fs,40);
不过有个地方不知道具体怎么做:
如果这个FileInfo对象的有个属性是一个数组的话,通过GetFieldID()这个JNI函数怎么取得这个数组?
又怎么把这个数组和结构体内的数组对应起来呢?
////////
JNI里面也有专门处理数组的函数,其实如果你足够了解java的话也应该知道数组也是一个object,其签名为[xtype的形式,其中x为[的数量,type为数组类型,例如[[i相当于int[][],[[Ljava/util/Date相当于Date[][]。所以数组本身也可以用GetObjectClass来获得,但是处理数组元素需要专门的jni内置函数来处理。
最后提醒你一句,一定要记得回收内存噢。jni的字符串与数组最容易出现内存泄漏。
例如:FileInfo类有个属性是 int ss[5]:
public class FileInfo{ public int filesize; public int ss[] = new int[5]; }
jfieldID ss = (env)->GetFieldID(objectClass,"ss","[I"); //这样是不是可以获取到int型的数组ss了?
如果可以的话,怎么对这个ID ss进行实际的访问操作?
jint jfs=(*env)->GetObjectField(env,cl,fs); //通过ID取得具体的数组
///////////
jfieldID fs = (env)->GetFieldID(objectClass,"filesize","I");
这样只是获得对象字段的句柄指针,并没有获得字段的值,要获得字段的值还需要其它操作,例如:
jint jfs=(*env)->GetObjectField(env,cl,fs);
如果获得的是jstring类型或者是数组类型还需要进行转换,转换成char[]类型或者char*类型,例如
char* str=(*env)->GetStringUTFChars(env,jstr,NULL);
如果是基本数据类型数组的话,访问其内部元素用GetXxxArrayElements(env,jarray,0);函数Xxx是类型名称,返回Xxx*类型,
如int * i=GetIntArrayElements(env,jint,0)
如果是对象型数组就是jobject jobj=GetObjectArrayElement(env,jobjectArray,jsize),jobject是数组变量,jsize是偏移量,返回值是数组中对应偏移量的值。
举例,java用一个类作为参数传递给C++的函数,C++内部声明了一个结构体来对应这个类的属性
类中有个属性是个int型的数组:int info[30]
在JNI封装函数中这样写:
//取得类对象 jclass objectClass = (env)->GetObjectClass(sobj); //sobj即传递进来的类的对象 //取得该数组属性的ID jfieldID jarr_info = (env)->GetFieldID(objectClass,"info","[I"); //参数“[I”表示这个是int型数组 //通过ID取得具体的数组 jintArray jintarr = (jintArray)(env)->GetObjectField(sobj,jarr_info); //参数sobj是该封装函数自动参数(JNIEnv *env, jclass sobj)中的jclass //以上部分执行没有问题,问题出在下面语句: //要对数组进行操作,要取得该数组的数组指针,通过JNI的函数GetIntArrayElements()来取得: jint *pia = (env)->GetIntArrayElements(jintarr,0);
public class FileInfo{ public String name; }JNI中:
//取得类对象
jclass objectClass = (env)->GetObjectClass(sobj); //sobj即传递进来的类的对象:new FileInfo()
//取得该String属性的ID
jfieldID jname = (env)->GetFieldID(objectClass,"name","Ljava/lang/String;"); //参数“Ljava/lang/String;”表示这个是String型
//取得该属性的具体值:
jstring js = (jstring)(env)->GetObjectField(sobj,jname);