android - 在android上如何从主线程中的一个线程执行一个c++函数并等待执行完成
问题描述
线程 1 是主线程。我有一个在线程 2 中执行的 c++ 代码(我产生的工作线程)。我想在主线程中执行本机函数并等待结果
printf("I am on thread : %s", getthreadid());
int ret = executeOnMainWait(mynativefunc1("hello"));
printf("ret : %d", ret);
printf("I am on thread : %s", getthreadid());
bool b = executeOnMainWait(mynativefunc2(4, 5));
printf("b : %d", b);
int mynativefunc1(char* param) {
printf("mynativefunc1 I am on thread : %s", getthreadid());
if(strcmp(param, "hello")) {
return 1;
}
return 2;
}
bool mynativefunc2(int val1, int val2) {
printf("mynativefunc2 I am on thread : %s", getthreadid());
return (val1 + val2) == 5;
}
所以这段代码应该显示:
I am on thread 2
mynativefunc1 I am on thread 1
ret : 1
I am on thread 2
mynativefunc2 I am on thread 1
b : true
我认为我们需要通过jni进入java世界并使用处理程序并将一些内容发布到主线程然后等待它完成,但问题我不知道如何直接使用自己的参数传递函数指针。这个例子只展示了 2 个原生函数,但实际上我有 20 个。非常感谢
解决方案
怎么做(有些部分是伪代码):
Java code:
public native void startSecondThread();
public native void fakeCallbackFromJava();
public native void fakeCallbackFromJava2();
public void blockingMethod(int chooseCallbackMethod, @Nullable Object obj, @Nullable String string) {
final Object syncObj = new Object();
runOnUiThread(new Runnable() {
@Override
public void run() {
...run Java code here in UiThread...
...here you can use OBJ and STRING arguments...
//call callbacks according to Argument
if (chooseCallbackMethod == 1) fakeCallbackFromJava();
else if (chooseCallbackMethod == 2) fakeCallbackFromJava2();
syncObj.notify();
}
});
syncObj.wait();
//we arrive HERE only after "syncObj.notify()" is called
}
C++ Thread code:
void foo() {
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
..."env" is currently synced object that could be used for Java calls...
...all following rows depends of what you want to call in Java...
jclass class = env->GetObjectClass(...);
jmethod method = env->GetMethodID(class, "blockingMethod", "ILjava/lang/Object;Ljava/lang/String;");
//first call
env->CallVoidMethod(method, 1, null, env->NewStringUTF("hello"));
//(you will arrive HERE only after "blockingmethod(1,null," hello")" is finished from Java UiThread)
//second call
env->CallVoidMethod(method, 2, null, null);
//finishing second thread
jvm->DetachCurrentThread();
}
C++ starting Thread:
#include <thread>
JavaVM *jvm;
JNIEXPORT JNICALL void Java_com_your_package_startSecondThread(JNIEnv* env, jclass clazz) {
env->GetJavaVM(&jvm);
std::thread first (foo);
first.join();
}
C++ Callback:
JNIEXPORT JNICALL void Java_com_your_package_fakeCallbackFromJava(JNIEnv* env, jclass clazz) {
...code called from Java MainThread/UiThread as CALLBACK for arguments: 1,null,"hello"...
}
JNIEXPORT JNICALL void Java_com_your_package_fakeCallbackFromJava2(JNIEnv* env, jclass clazz) {
...code called from Java MainThread/UiThread as CALLBACK for arguments: 2,null,null...
}
推荐阅读
- python - 我使用此代码使用 selenium 和 Python 进行无限滚动,但它没有无限滚动
- c - 使用python脚本找出C文件中是否存在嵌套注释
- mysql - mysql查询仅在满足某些条件时才将条件应用于where子句
- python - python3.8 因“致命 Python 错误:config_get_locale_encoding”而失败
- php - 无法在 Laravel 6.x 中安装 laravel/ui
- c# - 使用数据保护 API 存储签名密钥
- php - 获取laravel关系时将键设置为差异键
- sql - Postgres 中的唯一约束是否创建索引?
- java - 在 Java 中使用 For 循环打印模式
- reactjs - 接口根据其定义的属性推断类型