JNI调用c++函数,该函数的参数是结构体,句柄等非基本类型,求解决方案

ryrx 2009-04-16 10:33:40
做一个项目,第三方提供了一系列的C++函数接口。
现在我在用vc.net2005封装这些函数,即自己再定义一个c函数来调用这些接口。
例如:
(1).第三方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];
};

问题:这个结构体我该做一个class来对应吗?怎么写呢?里面有个结构体数组,头痛ing 。。。
我做一个JNIEXPORT jint JNICALL Java_N_api_get_logfile(JNIEnv *env, jobject, jobject)的封装函数
怎么把这个class和参数tfile这个结构体对应传递?



(2)另一个接口 int api_set_cvltgr(HWND hwnd, UINT ut, LPARAM lm),这个参数对应的java类型是什么?怎么传递?

(3)另一个接口 Struct fileinfo *api_get_inifile(char *name), 这个接口返回值是个结构体指针,JNI函数里怎么写啊?

小弟初学JNI,java项目也是第一次,很多地方没有头绪,网上的资料都是一些最基本的类型参数,这种复杂的求达人们指教,万分感谢!
...全文
3002 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
rickhunterchen 2012-02-11
  • 打赏
  • 举报
回复
建议LZ可以使用JNA,也就是JNI的扩展包。省去了自己写C++程序的问题。JNA的唯一不足就是无法用于C调用Java,而JNI却可以。

另外,Java与C之间的调用,接口函数的参数最好不要使用指针形式,用TCHAR数组作为参数类型,传递比较方便。
maggiccrystal_3 2012-02-10
  • 打赏
  • 举报
回复
楼主,如果 c++中有一方法获取了DisInfo d的一个对象,我想把这个d中的值传给 java中的实例类 DisInfo djava,那怎么实现?
JNIEXPORT jobject JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStruct
JNIEnv *env, jobject obj)
{
DisInfo d=Java_com_sundy_jnidemo_Test_GetDisInfo();
//在这里如何把d中的值给obj?


}
小坏蛋rubys 2009-05-01
  • 打赏
  • 举报
回复
Java 深度探索者 QQ群: 65670864
ryrx 2009-04-29
  • 打赏
  • 举报
回复
最新的一个问题是:
参数是一个类对象数组,传递进C++函数后,先将对应的结构体赋值,然后改变结构体的值,再返回给这个对象数组,最后通过java打印出该返回数组的每个属性值。

结构体定义如下:

struct fileinfo{
char *fullpath;
int filesize;
struct disnode *tnode;
};

struct disnode{
int number;
int stat[32];
};



java类定义如下:

public class FileInfo{
public String fullpath;
public int filesize;
public DisNode dn = new DisNode();
}

public class DisNode{
public int number;
public int[] stat = new int[32];
}



JNI封装函数定义:

JNIEXPORT jint JNICALL Java_TestJni_makefiles
(JNIEnv *env, jclass obj,jobjectArray objAry)


请问如下问题:
1.jfieldID是对象数组中的每个类对象都要提取一次,还是只要取一个对象,大家都可以用?
2.传递入的是对象数组,那对应赋值给结构体的时候,结构体也必须是数组,那循环赋值时类对象如何一一提取出来?
3.结构体值被更改后,赋值回对象数组,该数组如何返回?
以上最好有简单的例子,谢谢!
ryrx 2009-04-29
  • 打赏
  • 举报
回复
我自己试了一下,

jobject sobj = (env)->GetObjectArrayElement(objAry,0);

//get java instance
jclass objectClass = (env)->GetObjectClass(sobj); //编译通过,但执行错误


用GetObjectArrayElement函数从数组得到的object无法用GetObjectClass函数进行class类型提取,求解!
IThurricane 2009-04-27
  • 打赏
  • 举报
回复
支持下
ryrx 2009-04-27
  • 打赏
  • 举报
回复
哎,原来强制就可以了。谢谢!
qybao 2009-04-27
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 ryrx 的回复:]
class中有个属性为String类型:


C/C++ code
public class FileInfo{
public String name;
}





JNI中:

C/C++ code
//取得类对象
jclass objectClass = (env)->GetObjectClass(sobj); //sobj即传递进来的类的对象:new FileInfo()
//取得该String属性的ID
jfieldID jname = (env)->GetFieldID(objectClass,"name","Ljava/lang/String;"); //参数“Ljava/lang/String;”表示这个是String型
//取得该…
[/Quote]

强行转换呢
jstring js = (jstring)(env)->GetObjectField(sobj,jname); //这里报错!
ryrx 2009-04-27
  • 打赏
  • 举报
回复
class中有个属性为String类型:


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 = (env)->GetObjectField(sobj,jname); //这里报错!



错误提示说不能将jobject型转为jstring型,这个怎么办?
查网上的例子,说jstring型就是jobjcet型啊,为什么不行?

  • 打赏
  • 举报
回复
学习来的
qingfeng_yijiu 2009-04-26
  • 打赏
  • 举报
回复
路过!!!分数挺高.拿不到.帮顶
ryrx 2009-04-24
  • 打赏
  • 举报
回复
谢谢楼上,果然是这里的问题^_^
qybao 2009-04-23
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 ryrx 的回复:]
哪里写错了啊?看不出来啊
[/Quote]
jclass objectClass = (env)->GetObjectClass(sobj); //sobj
...
jintArray jintarr = (jintArray)(env)->GetObjectField(obj,jarr_info); //0bj->sobj
ryrx 2009-04-23
  • 打赏
  • 举报
回复
哪里写错了啊?看不出来啊
树成 2009-04-23
  • 打赏
  • 举报
回复
我都吧函数的定义发给你了,这你还写错,哎..........
ryrx 2009-04-23
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 qybao 的回复:]
引用 21 楼 ryrx 的回复:
请问memcpy的参数obj是指什么?如果指的是传递进来的类对象的话,我试了,结构体内容这样赋值给类对象是不行的呀
我是看了你的jclass objectClass = (env)->GetObjectClass(obj); 这个写的
这个obj就是传进来的FileInfo的instance
memcpy(obj, ff, sizeof(fileinfo))
用这个方法还有个问题,java和C++的类型长度不一定一样,
所以估计还是要一个一个的属性去设置
当然,如果能保证类型长度…
[/Quote]

是的,我现在就是手动一条一条赋值的,累死人了,该死的结构体还定的这么复杂,问候原代码的主人一百遍啊一百遍!
ryrx 2009-04-23
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 qybao 的回复:]
引用 20 楼 ryrx 的回复:
引用 19 楼 qybao 的回复:
引用 16 楼 ryrx 的回复:
jint *pia = (env)->GetIntArrayElements(jintarr,0);

jint *pia = (env)->GetIntArrayElements(env, jintarr,0); //your parameter is wrong


没错啊,C++里前面用(env)的话,后面就两个参数了。这个不错的,不然编译不通过的。
现在是编译通过,执行出错。

恩,我刚才把jni.h头文件看了一下了,里面对JNIEnv结构体的定义,…
[/Quote]

JNI涉及了java和C++两部分语言,目前我可以调试java部分,C部分没有办法调试,所以才在每一句JNI函数后加一个输出语句,就是为了判断哪里会出现问题的。

这个东东还真是搞死人了呀。。。。。
qybao 2009-04-23
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 ryrx 的回复:]
请问memcpy的参数obj是指什么?如果指的是传递进来的类对象的话,我试了,结构体内容这样赋值给类对象是不行的呀[/Quote]
我是看了你的jclass objectClass = (env)->GetObjectClass(obj); 这个写的
这个obj就是传进来的FileInfo的instance
memcpy(obj, ff, sizeof(fileinfo))
用这个方法还有个问题,java和C++的类型长度不一定一样,
所以估计还是要一个一个的属性去设置
当然,如果能保证类型长度一样的话,用memcpy最方便
wang1231 2009-04-23
  • 打赏
  • 举报
回复
进来学习学习!
加载更多回复(22)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧