C++注册函数给JAVA调用
扫描二维码
随时随地手机看文章
网络上根本没人说这么个玩意, 包括一些写书的老怪物.甚至他们的写法都是非线程安全的。JAVA调用C++有2种方式,第一种很累需要把函数写成JAVA规定的格式,第二种很绕,需要让JAVA事先主动调用C++,C++根据他传递过来的类指针来操作。现在说的是不需要对应安卓类名直接注册的机制,关键是QT能用。因为Qt中无法用JNI_OnLoad,因此我说的这个东西很重要。Qt中的新类:QtAndtoid提供了在JAVA UI线程环境中执行C++代码的功能:runOnAndroidThreadSync。
示例:JAVA中按返回键通知QT OnESCdown函数将由C++注册给java调用
public native void OnESCdown(); @Override public boolean onKeyDown(int keyCode, KeyEvent event) { OnESCdown();//通知C++层的 onEscDown函数 Log.i("mod:","keycode:"+keyCode); if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, keyCode, event); else return super.onKeyDown(keyCode, event); }
C++:
static void onEscDown() { qDebug()<<"C++ onEscDown"; } st atic const JNINativeMethod gMethods[] = { //定义批量注册的数组,是注册的关键部分 { "OnESCdown", "()V", (void*)onEscDown } // func2是在java中声明的native函数名,"()V"是函数的签名,可以通过javah获取。 }; void RegJni() { QtAndroid::runOnAndroidThreadSync([=](){ QAndroidJniEnvironment EV; qDebug()<<"RegisterNatives 0***********"; qDebug()<<"RegisterNatives 1***********"; const char* kClassName ="org/qtproject/qt5/android/bindings/QtActivity"; jclass clazz; clazz =EV->FindClass(kClassName); if (clazz == NULL) { qDebug()<<"erro clazz"; return ; } qDebug()<<"RegisterNatives 2***********"; if (EV->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK) { printf("register native method failed!n"); return; }else{ qDebug()<<"RegisterNatives 搞定***********"; } }); //这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中。 这里说明,动态库和有native方法的类之间,没有任何对应关系。 // QAndroidJniObject javaClass(kClassName); // clazz = env->GetObjectClass(javaClass.object()); // qDebug() <<"find ExtendsQtNative"<< clazz; EV->DeleteLocalRef(clazz);//删除引用避免内存泄漏 qDebug()<<"RegisterNatives OK***********"; }