WebAssembly从C调用JavaScript函数作为函数指针



我想将一个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-具有代码-全功能-从c开始的点。为此,他们有一个名为addFunction的函数。

我在这里看了一下它的实现:https://github.com/emscripten-core/emscripten/blob/incoming/src/support.js#L755

看起来很。。。脾气暴躁。看起来他们正在创建一个新的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;
}

这是一个粗略的例子来展示这个概念。实际实现检查功能是否已经转换、处理错误等。

函数表是Wasm中函数指针的基元。函数指针必须使用一个。管理这个单独的地址空间可能非常棘手,emscripten中所有的"黑客"代码都是为了确保安全完成。在你自己的代码中,你不需要像emscripten那样强制执行那么多不变量,所以你可能可以去掉大部分。很高兴在评论中澄清这一点。

您可以在emscripten 导出函数的帮助下签出这个简单的生成器

https://libamtrack.github.io/c2JsGenerator/

相关内容

  • 没有找到相关文章

最新更新