运行在Android UI的C++代码(主)线程,你将不得不使用Android弯针(activity.getMainLooper()或Looper.getMainLooper()在Java中):
jmethodID getMainLooperMethod = jniEnv->GetMethodID(mainActivityClass, "getMainLooper", "()Landroid/os/Looper;");
jobject mainLooper = jniEnv->CallObjectMethod(mainActivity, getMainLooperMethod);
“mainActivity”是android.app.Activity的一个实例,它是从Java传递给JNI的,但您也可以简单地使用Looper类的静态getMainLooper方法。接下来,您要创建处理程序类的(新的处理程序(mainLooper在Java中)的实例:
jclass handlerClass = jniEnv->FindClass("android/os/Handler");
jmethodID handlerConstructor = jniEnv->GetMethodID(handlerClass, "<init>", "(Landroid/os/Looper;)V");
postMethod = jniEnv->GetMethodID(handlerClass, "post", "(Ljava/lang/Runnable;)Z");
handler = jniEnv->NewObject(handlerClass, handlerConstructor, mainLooper);
handler = jniEnv->NewGlobalRef(handler);
要知道,你有存储处理器(jobject)后使用它 你必须写一个爪哇位来实现Runnable接口,因此这一代码进入Java中:
package my.package;
import java.lang.Runnable;
public class Runner implements Runnable
{
native public void run();
}
正如你所看到的run()方法是本地的,所以我们可以用C实现它++如下:
extern "C" JNIEXPORT void JNICALL
Java_my_package_Runner_run(JNIEnv*, jclass)
{
// here goes your native code
}
现在,你必须获得亚军类及其构造函数C++:
runnerClass = jniEnv->FindClass("org/ouzelengine/Runner");
runnerClass = static_cast<jclass>(jniEnv->NewGlobalRef(runnerClass));
runnerConstructor = jniEnv->GetMethodID(runnerClass, "<init>", "()V");
商店runnerClass(JCLASS)和runnerConstructor(jmethodID)的地方以备后用。你必须做的最后一件事实际上是创建亚军类的实例,并将其发布到处理程序:
jobject runner = jniEnv->NewObject(runnerClass, runnerConstructor);
if (!jniEnv->CallBooleanMethod(handler, postMethod, runner))
{
// something wrong happened
}
我在Ouzel engines代码做的是我创建的std ::函数的队列中,并且保护它与互斥体。无论何时我需要在Android UI线程上执行std :: function,我都会将std :: function实例添加到队列中,并将其从队列中弹出并在本地方法(Java_my_package_Runner_run)中执行。
这是最接近你写不用Java代码(你将不得不写6行来实现Runnable接口)。
据我所见,native-to-java调用应该在一些非主线程上发出?然后你想发送调用主线程,并等待结果准备好了吗? – Sergio
感谢您提出的问题,我想了很多,并编辑了这个问题,我将如何将它想象为理想的工作。是否有意义? – keyboard