JNI中实现类似C++回调的方法(1)

669 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

前些日子刚刚解决了Java调用C++代码的中间键搞定,这不,又有新的功能了,还要在写so文件,其实我的内心十分的吐槽,左一个右一个的,直接用java写不香吗,搞的C++程序员还得写个中间键,哎!就当自己多了项技能吧!

今天我们就来讲述下如何JAVA在调用so文件时,如何实现类似于C++回调的方法吧!

对于回调,C++程序员应该都不陌生吧!

回调函数就是一个通过函数指针调用的函数。如果你把函数指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数

在纯C++类中实现回调方法不是很难,那么,在JNI中让Android调用时,中间出现了回调该怎么使用呢?

C++中回调函数的调用方式:

定义一个回调函数

typedef void (*CallBackFun)(int nData1, std::string sData2);

定义回调函数

CallBackFun m_pCallBackFun;

在使用类中注册该函数

void SetCallOperation(CallBackFun fun)
{
    m_pCallBackFun = fun
}

上述内容完成后我们就可以使用回调函数传递信息了。

根据C++中的回调方式,让我们的Android程序也能实现类似C++中的回调。

在JNI文件中,定义两个类指针:

JNIEnv *mJni;
jobject mJobject;

当我们自动生成动态接口函数时,会发现,生成的函数接口中,默认会带有两个参数,第一个参数就是JNIEnv,第二个参数就是jobject。其次才是我们函数中有效的参数。

在Native中不存在回调的方法,在JNI文件中的回调只是Native调用JAVA函数的方法。

最终的调用形式,如下所示:

jmethodID mid = mJni->GetMethodID(cls, "CallBackFunAndroidBack", "(ILjava/lang/String;)V");

mJni->CallVoidMethod(mJobject, mid, 参数1,参数2);

使用上述两句代码就可以让JAVA函数接收我们传入的参数了。

在这里需要注意以下几个方面:

1:GetMethodID中传入的函数名一定与JAVA环境中调用的函数名保持一致。

2:书写参数时一定要记得使用JAVA自身系统的类时,例如:String类,必须配备";"否则会出现错误。我在开发过程中写的参数较多,一时之间忘记了最后一个分号。导致Android调用总是出现问题,还调试了很长时间。这都是教训呀!

3:在使用JNI自带的CallVoidMethod时,一定要分情况而言,该函数只能传递返回值为void类型的回调

4:回调函数中有多少个参数,JNI的回调类中必须要写全!

以上就实现了简单的参数回调了,那么对于一些复杂的传参来说,比如:需要给Android传入一个类似于std::vector<结构体> 的数据,该如何进行回调呢?这个功能有一些繁琐,下一篇文章我们进行更新哟~

先尝试下这个简单的功能吧!

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