【问题标题】:How to use WebAssembly from node.js?如何从 node.js 使用 WebAssembly?
【发布时间】:2018-12-26 10:49:30
【问题描述】:

我目前正在处理一个个人 Node.js (>=8.0.0) 项目,该项目需要我调用 C 子例程(以缩短执行时间)。我正在尝试使用 WebAssembly 来执行此操作,因为我需要我的最终代码在浏览器中打开时兼容。

我已经使用 Emscripten 将 C 代码编译成 WebAssembly,但不知道如何进行。

在正确方向上的任何帮助都会很棒。谢谢!

【问题讨论】:

    标签: node.js emscripten webassembly


    【解决方案1】:

    感谢@sven。 (只翻译)

    test.c:

    #include <emscripten/emscripten.h>
    
    int EMSCRIPTEN_KEEPALIVE add(int a, int b) {
        return a + b;
    }
    

    编译:

    emcc test.c -O2 -s WASM=1 -s SIDE_MODULE=1 -o test.wasm
    

    test.js:

    const util = require('util');
    const fs = require('fs');
    var source = fs.readFileSync('./test.wasm');
    const env = {
      __memory_base: 0,
      tableBase: 0,
      memory: new WebAssembly.Memory({
        initial: 256
      }),
      table: new WebAssembly.Table({
        initial: 0,
        element: 'anyfunc'
      })
    }
    
    var typedArray = new Uint8Array(source);
    
    WebAssembly.instantiate(typedArray, {
      env: env
    }).then(result => {
      console.log(util.inspect(result, true, 0));
      console.log(result.instance.exports._add(10, 9));
    }).catch(e => {
      // error caught
      console.log(e);
    });
    

    【讨论】:

    【解决方案2】:

    您可以在没有 JS 胶水文件的情况下构建 .wasm 文件 (standalone)。有人回答过类似的question

    创建一个 test.c 文件:

    int add(int a, int b) {
      return a + b;
    }
    

    构建独立的 .wasm 文件:

    emcc test.c -O2 -s WASM=1 -s SIDE_MODULE=1 -o test.wasm
    

    在 Node.js 应用程序中使用 .wasm 文件:

    const util = require('util');
    const fs = require('fs');
    var source = fs.readFileSync('./test.wasm');
    const env = {
        memoryBase: 0,
        tableBase: 0,
        memory: new WebAssembly.Memory({
          initial: 256
        }),
        table: new WebAssembly.Table({
          initial: 0,
          element: 'anyfunc'
        })
      }
    
    var typedArray = new Uint8Array(source);
    
    WebAssembly.instantiate(typedArray, {
      env: env
    }).then(result => {
      console.log(util.inspect(result, true, 0));
      console.log(result.instance.exports._add(9, 9));
    }).catch(e => {
      // error caught
      console.log(e);
    });
    

    关键部分是WebAssembly.instantiate()的第二个参数。没有它,您将收到错误消息:

    TypeError: WebAssembly 实例化: Imports 参数必须存在 并且必须是一个对象 在 在 process._tickCallback (internal/process/next_tick.js:188:7) 在 Function.Module.runMain (module.js:695:11) 启动时(bootstrap_node.js:191:16) 在 bootstrap_node.js:612:3

    【讨论】:

    • 虽然我几天前就想出了答案,但您的回答帮助我更好地理解了。谢谢!
    • 获取LinkError: WebAssembly Instantiation: Import #0 module="env" function="__memory_base" error: global import must be a number
    • 该示例不适用于节点 10.x 和 8.91。和 emcc 1.38.21。与@JBaczuk 相同的错误:LinkError: WebAssembly Instantiation: Import #0 module="env" function="__memory_base" error: global import must be a number
    • 发现问题:test.c #include int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a+b; } Node.js 应用程序:将memoryBase 替换为__memory_base
    • 使用节点 8.93 我得到 LinkError: WebAssembly Instantiation: table import 0 is小于 minimum 2, got 0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 2023-01-24
    • 2023-02-08
    • 2018-04-15
    • 1970-01-01
    • 2020-08-23
    相关资源
    最近更新 更多