iOS上的c ++,如何将抽象类型变量移动到线程中?
Posted
技术标签:
【中文标题】iOS上的c ++,如何将抽象类型变量移动到线程中?【英文标题】:c++ on iOS, how to move abstract type variable into thread? 【发布时间】:2021-06-05 09:56:26 【问题描述】:我正在尝试使用新的 JSI 绑定为 react-native 创建一个 SQLite 库/适配器。 JSI 绑定只是 javascript Core(还有 hermes 和 V8?)之上的一层,它允许直接从 javascript 调用 c++。
对于我的问题而言,有很多代码不是很重要,但基本上,同步调用工作正常,但现在我正在尝试创建一个线程来执行异步工作,然后解决一个 javascript 承诺。
在下面的代码中,我创建并返回了一个 Promise,然后尝试生成一个线程来执行后台工作。
auto asyncExecSQL = jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forAscii(rt, "sequel_asyncExecSQL"),
1,
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
jsi::Value promise = rt.global().getPropertyAsFunction(rt, "Promise").callAsConstructor(
rt,
jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forAscii(rt, "executor"),
2,
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t) -> jsi::Value
jsi::Function cb = args[0].asObject(rt).asFunction(rt);
auto resolve = std::make_shared<jsi::Function>(std::move(cb));
thread t1([rt, resolve] // ERROR: By-copy capture of value of abstract type 'jsi::Runtime'
resolve->call(rt, jsi::Value(42));
);
return ;
));
return promise;
);
rt.global().setProperty(rt, "sequel_asyncExecSQL", move(asyncExecSQL));
你可以或多或少地忽略所有的 jsi:: mumbo-jumbo,它更少地从 c++ 端操作 javascript 对象。可以看到Runtime
对象很重要,需要它来操作和创建对象。
问题是,我正在尝试创建一个线程来在后台执行获取代码,我不知道将rt
(运行时)对象移动/共享到线程中的语义。
谁能向我解释我做错了什么?
【问题讨论】:
【参考方案1】:设法让它工作:
auto asyncExecSQL = jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forAscii(rt, "sequel_asyncExecSQL"),
1,
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
string query = args[0].asString(rt).utf8(rt);
jsi::Value promise = rt.global().getPropertyAsFunction(rt, "Promise").callAsConstructor(
rt,
jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forAscii(rt, "executor"),
2,
[query](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t) -> jsi::Value
thread t1([&rt, &query, resolve std::make_shared<jsi::Value>(rt, args[0]) ]
cout << "Trying to exec" << query << endl;
vector<jsi::Object> results = sequel_execute(rt, query);
auto res = jsi::Array(rt, results.size());
for(int i = 0; i < results.size(); i++)
res.setValueAtIndex(rt, i, move(results[i]));
resolve->asObject(rt).asFunction(rt).call(rt, res);
);
t1.detach();
return ;
));
return promise;
);
【讨论】:
正是我想要的。顺便说一句,很棒的博客!希望一旦 turbomodules 正式发布,我们会得到一些不错的文档。 由于某些原因在android上虽然当promise被解析时RN线程不会自动更新:即,一旦在c ++端调用resolve函数,就不会触发像§...().then((value) => setState(value))
这样的事情。它仅在重新渲染 ui 时触发。它在 ios 上按预期工作。
其实在ios上加this_thread::sleep(2s)
也很明显
你最好从 msrousavy 研究 react-native-mmvk 或 react-native-background-task,他以不同的方式实现后台任务
是的,我浏览了他的仓库。当他从复活的地方导入代码时,他失去了我。所以他的代码只是创建了一个执行器,但是 react 和 c++ 世界之间的整个通信是由复活的库完成的......以上是关于iOS上的c ++,如何将抽象类型变量移动到线程中?的主要内容,如果未能解决你的问题,请参考以下文章
如何将C / C ++库代码封装为可在具有多个实例的单独线程中运行?
如何将 android 工具添加到我在 mac 上的路径中? [复制]