【发布时间】:2019-12-23 18:01:45
【问题描述】:
我想将一个 JavaScript 函数作为参数传递给一个从 WebAssembly 导出的函数,并将函数指针作为参数。
考虑以下示例:
JavaScript 代码:
function foo() {
console.log("foo");
}
wasmInstance.exports.expects_funcptr(foo);
C 代码:
typedef void(*funcptr_type)(void);
void expects_funcptr(funcptr_type my_funcptr)
{
my_funcptr();
}
我没有使用 Emscripten,但他们在“与代码交互”页面中有一个关于该主题的部分:https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-function-pointers-from-c。为此,他们有一个名为 addFunction 的函数。
我在这里查看了它的实现:https://github.com/emscripten-core/emscripten/blob/incoming/src/support.js#L755
而且看起来很... hacky。看起来他们正在创建一个新的 wasm 模块,该模块将 javascript 函数作为导入并将其作为 wasm 函数导出。只有这样他们才能将函数添加到 WebAssembly 表中。
有没有更好的方法来做到这一点?
编辑:
这是我目前的处理方式。通过使用以下函数将 JS 函数转换为 WASM,我可以像这样将 JS 函数传递给 WASM:
// How the above example would be called using the converter function.
wasmInstance.exports.expects_funcptr(convertFunction(foo, Types.VOID));
// The actual converter function (minus some details for simplicity)
function convertFunction(func, ret, params) {
// Construct a .wasm binary by hand
const bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, // magic
0x01, 0x00, 0x00, 0x00, // version
// ... generate type, import, export sections as well
]);
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module, {
a: {
b: func
}
});
const ret = table.length;
table.grow(1);
table.set(ret, instance.exports.f);
return ret;
}
这是一个粗略的例子来展示这个概念。实际的实现会检查函数是否已被转换、处理错误等。
【问题讨论】:
-
你的目标到底是什么?还是不想用 Emscripten 导入 JS 功能?请注意,这不是黑客攻击。 Emscripten 也不会创建新的 wasm 模块。
-
@BumsikKim 我的目标是能够从 C 调用 JavaScript 函数作为函数指针。我想将 JavaScript 函数作为参数传递给从 WebAssembly 导出的函数指针作为参数。我目前没有使用 Emscripten,也不想使用。
标签: webassembly