首页>>后端>>java->JNI中实现类似C++回调方法

JNI中实现类似C++回调方法

时间:2023-12-07 本站 点击:0

上篇文章讲述了JNI中C++简单的调用Java函数,接下来我们要解决上次留下的疑惑问题进行解答,如何调用带有结构体的java函数。

假设:C++要给Java传入一个叫做DataSt的结构体,那么,Android也需要定义同样的结构体,保持与so文件中的结构体名称以及字段保持一致,否则查询不到。

结构体内容如下:

struct DataSt{    std::string id;    std::vector<int> vetIndex;}

C++传入的数据保存在:std::veC++tor m_vetArray中,在java中是如何接收带有STL的结构体数据呢?

接下来我会逐步进行讲解~

调用讲解

1:定义Java结构体

为了让java代码中获取到C++调用的数据时,此时JAVA中需要定义这样一个DataSt的结构体。

查询JAVA中定义结构体的位置

jclass objClass = mJni->FindClass("cn/test/model/java2so/event/DataSt");

注意此时FindClass对应的就是Java中定义结构体的程序路径,一定要写全,否则无法查询到!

2:创建一个java数组对象

与C++方法一样,想要把数据存储到容器中,需要定义一个这样的容器,这里需要明确容器的大小,也就是需要传给JAVA数据的大小,类似于C++的数组。

int nsize = 10; //假设,需要给java传入10组结构体数据,这里根据实际情况自行定义//创建:数组对象jobjectArray arrayData = mJni->NewObjectArray(nsize, objClass, NULL);if(arrayData == nullptr){    //此时,说明new出来的数组无效    return;}

3:设置JAVA方法

结构中存在了两种变量类型:string、int

获取id方法ID

jmethodID method_id = mJni->GetMethodID(objClass, "setId", "(Ljava/lang/String;)V");

获取vetIndex中一条int值的方法ID

jmethodID method_index = mJni->GetMethodID(objClass, "setIndex", "(I)V");

如果这里不知道如何获取方法,可以结合java结构体自动生成的函数一一对应。

4:类型转换

想要让Java识别C++的数据,我们就需要对类型进行转换,依据DataSt中的两种结构类型进行处理转换

4.1:string -> jstring

假设:string id = "123";

jstring jname = mJni->NewStringUTF(str.c_str());

4.2:int类型

注意:在jni中,int类型是直接可以赋值的,不需要特殊处理

5:遍历方式存储成java结构

这里到了我们存储的重点了,上面的内容都是为这一步做的铺垫。

在第二步骤时,我们假设了C++容器的大小为10,那么,我们这里依旧用10做处理

int nsize = 10;

我们在进行数据存储是,是按照顺序的方式存储,首先我们要定义一个下标方法。

jmethodID method_init_Event = mJni->GetMethodID(objClass, "<init>", "()V");

在进行数据存储时,需要用到这个method_init_Event参数的

在C++中插入一条数据时,例如vector直接push_back方法就可以了,或者也可以使用insert方法。

下面,先将存储的大体框架展示出来

for (int i = 0; i < nsize; i++){    DataSt stInfo = m_vetArray[i]; //C++结构体中的一条数据    //1:创建一个对象用于存储一条数据    jobject objmodel = mJni->NewObject(objClass, method_init_Event, "");    //2:赋值操作    //2.1:将id数据设置到objmodel对象中    //2.2:将vetIndex数据设置到objmodel对象中    //3:将数据设置到Java的Arrary中    mJni->SetObjectArrayElement(arrayData, i, objmodel); }

以上就是粗略的赋值流程了,针对于2操作,我们进行具体的代码展示吧!

操作2.1:将id数据设置到objmodel对象中

第一步:string转成jstring类型

jstring jsId = mJni->NewStringUTF(stInfo.id.c_str());

第二步:存储到objmodel对象中

mJni->CallVoidMethod(objmodel, method_id, jname);

操作2.2:将vetIndex数据设置到objmodel对象中

jclass objClass = mJni->FindClass("cn/test/model/java2so/event/DataSt");0

6:C++调用Java函数传递参数

第五步骤中已经将数据存储到结构体中了,那么这里开始实际调用JAVA的函数了。

假设,这里被调用的函数名叫做:RecordDataAndroidBack(数组,bool类型)

jclass objClass = mJni->FindClass("cn/test/model/java2so/event/DataSt");1

代码解析:

出现函数调用错误时,最容易出现的问题就是JAVA函数参数的路径写的不对,或者是格式不正确,90%都是在第三个参数上出问题的,而且,有些问题还会跑偏,让你抓狂,让你无处可找!!

到这里,如何调用带有结构体容器的JAVA函数已经讲解完成了,小伙伴们尽情的尝试吧!

我是中国好公民st,一名C++开发程序猿~

原文:https://juejin.cn/post/7102361188113055752


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/18648.html