【问题标题】:WebAssembly Call JavaScript Functions as Function Pointers From CWebAssembly 从 C 调用 JavaScript 函数作为函数指针
【发布时间】: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


【解决方案1】:

函数表是 Wasm 中函数指针的原语。您将不得不使用一个函数指针。管理这个单独的地址空间可能非常棘手,emscripten 中的所有“hacky”代码都是为了确保安全完成。在您自己的代码中,您不需要像 emscripten 那样强制执行许多不变量,因此您可能可以摆脱其中的大部分。也很高兴在 cmets 中澄清这一点。

【讨论】:

  • 我的问题是表似乎是为从 wasm 中获取函数指针并进入 JS 而设计的,而不是像我想要的那样反过来。传递给表的 set 方法的值必须是导出的 wasm 函数。所以我不能只是将一个 JS 函数推入一个表中。自从我问了这个问题以来,我一直在使用我发现查看 emscripten 源代码的方法。我创建了一个导入 JS 函数并将其导出回来的小模块,以便我可以将其插入到表中。这行得通。感觉就像 JS API 缺少很好地处理这种情况的功能。
  • @Ghillie 他们被设计成双向的。只有很多新功能还没有实现。理想情况下你可以使用new WebAssembly.Function({ type descriptor }, fn),但我认为还没有。
  • 有没有一个地方可以让我跟踪即将推出的功能的进度,比如那个?我在 emscripten 源代码中看到了一条关于有朝一日获得 WebAssembly.Function 构造函数的可能性的评论。虽然我找不到任何其他信息。感谢您花时间回答这个问题。我会继续接受这个答案。
【解决方案2】:

您可以通过 emscripten 导出的函数帮助查看这个简单的生成器

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

【讨论】:

    猜你喜欢
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2022-01-25
    • 2013-03-31
    • 2012-04-16
    • 1970-01-01
    相关资源
    最近更新 更多