关于c++:在-WebAssembly-中实现回调的方式

11次阅读

共计 1322 个字符,预计需要花费 4 分钟才能阅读完成。

本文将介绍在 C++ 中实现 js 回调的几种形式. 在应用 wasm 的过程中, 防止不了要从 C++ 回调 js 的函数来实现异步交互.
官网文档 https://emscripten.org/docs/p…
中曾经介绍了 6 种实现回调的形式, 这里介绍几种能解决理论问题的形式。

EM_ASM 相干参数介绍

EM_ASM 函数簇蕴含

EM_ASM
EM_ASM_INT
EM_ASM_DOUBLE

相似的应用形式 :

EM_ASM_({postMessage({cmd: 'callback', text: "callback", threadId: $2, callId : $0, code : $1})
        }, callback, code, tid);

其中 $0$1$2 别离代表 callback, code, tid 的值.
前面两个函数还能够获取到 js 返回的 int/ double 值. 个别能满足简略的应用.

如何在 worker 中实现回调

应用 wasm 的时候, 某些工作会被放到 worker 中执行, 执行实现后回调告诉后果.

这个时候要特地留神: worker 和主线程是互相独立的, 并不能像一般的多线程能够共享过程内的数据. 在 worker 中调用 js 回调时, 第一个面临的限度就是 web worker 的限度:

  1. 不能拜访 window, document 对象
  2. 与主线程通信须要通过 post message 形式
  3. 不能拜访主过程中的全局变量会对象

如果间接在 worker 中间接调用回调, 就只能做一些简略的事件. 为此 emscripten 提供了以下函数:

MAIN_THREAD_EM_ASM
MAIN_THREAD_EM_ASM_INT
MAIN_THREAD_EM_ASM_DOUBLE
MAIN_THREAD_ASYNC_EM_ASM

顾名思义就是在主线程中执行函数. 然而后面 3 个函数不论在哪个线程调用都会会阻塞主线程.

举荐应用最初一个 MAIN_THREAD_ASYNC_EM_ASM, 区别就是在如果是主线程调用该函数, 会被了解执行, 如果是在其余线程调用, 则会被追加到主线程的工作队列再被执行.

至于如何实现这个性能了, emscripten 也冲破不了这个限度, 也是通过 postMessage 的通信机制实现的.

在不相熟 emscripten 的时候我本人模仿了这个过程:

  1. 在主线程注册函数, 保留在一个特定的对象中, 并产生一个 callid
  2. 把 callid 传到 worker 中, 应用上述的 EM_ASM 回调
  3. 子线程会把信息 post 到主线程
  4. 主线程收到 message 和 callid, 去特定的对象查找到曾经注册的回调函数, 执行函数, 实现回调

如何在回调中传递字符串

在 emscripten 值的传递, 除了根本类型是通过拷贝的, 字符串和数组, 内存都是通过指针地址去传递.

std::string data = "{\"code\": 0, \"msg\": \"/input.mp4\"}"
MAIN_THREAD_ASYNC_EM_ASM({var dataStr = UTF8ToString($0);
     console.log(dataStr)
}, data.c_str());

在回调函数中, 通过 UTF8ToString 函数把传递过来的指针转成 js 的字符串, 这样来达到传递字符串的目标.

正文完
 0