700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > JNI调用c++函数 该函数的参数是结构体(——对象的传递)

JNI调用c++函数 该函数的参数是结构体(——对象的传递)

时间:2020-12-02 12:42:29

相关推荐

JNI调用c++函数 该函数的参数是结构体(——对象的传递)

第三方C++函数接口为 int api_get_logfile(Struct fileinfo tfile),参数是个结构体,且套了另一个结构体:

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);

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。