JNI调用c++函数,该函数的参数是结构体(——对象的传递)
来源:互联网 发布:查网站域名是否被注册 编辑:程序博客网 时间:2024/06/05 11:21
struct fileinfo{
char *fullpath;
int filesize;
int filemode;
struct disnode *tnode;
};
struct disnode{
int number;
struct {
int node;
int stat;
}s[number];
};
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];}
在JNI的封装中:
jclass objectClass = (env)->GetObjectClass(obj); //obj就是FileInfo类的实际对象
jfieldID fs = (env)->GetFieldID(objectClass,"filesize","I"); //可以获取到int型的filesize这个属性了
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即传递进来的类的对象//取得该数组属性的IDjfieldID 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);
class中有个属性为String类型:
public class FileInfo{ public String name; }JNI中:
//取得类对象jclass objectClass = (env)->GetObjectClass(sobj); //sobj即传递进来的类的对象:new FileInfo()//取得该String属性的IDjfieldID jname = (env)->GetFieldID(objectClass,"name","Ljava/lang/String;"); //参数“Ljava/lang/String;”表示这个是String型//取得该属性的具体值:jstring js = (jstring)(env)->GetObjectField(sobj,jname);
- JNI调用c++函数,该函数的参数是结构体(——对象的传递)
- JNI调用c++函数,该函数的参数是结构体(——对象的传递)
- 函数调用的参数传递
- c/c++/java,函数调用的参数的传递方法
- 实现主函数将年、月、日(结构体类型)传递给days函数,days函数计算该年该月该日是该年的第几天并传回主函数输
- 在JNI中调用本地带结构体参数的函数
- 在JNI中调用本地带结构体参数的函数
- c函数的参数传递
- C函数的参数传递
- c#-函数的参数传递
- C#-函数参数的传递
- C/C++函数调用时的参数传递小结
- C语言函数调用传递参数时的类型退化
- arm c函数的调用过程arm汇编语言调用C函数之参数传递
- C或C++中函数的参数传递——值传递、指针传递、引用传递
- 函数的调用和参数的传递
- 关于在C/C++语言中,函数如何返回数组,数组如何作为参数传递以及返回数组的函数该如何调用问题的总结
- 彻底搞定C指针-——第五篇:函数参数的传递(值传递、地址传递、引用传递)
- 未来的日子,体感技术给力
- 程序员四大忌,你忽略了几条?
- poj1258
- VisualSVN Server&TortoiseSVN 版本控制平台搭建
- 看openflow中链表的组织方式
- JNI调用c++函数,该函数的参数是结构体(——对象的传递)
- Fedora13 安装Google浏览器出错及其解决办法
- linux 经典命令(一)
- 程序员新年要做的10个决定
- C语言宏与强制类型转换的妙用
- 算法问题《Card Game》的数学模型和Java实现
- 编写时间的类函数
- 别放弃每一次的进步
- 第三周实验报告1