如何在node.js中使用WebAssembly?

11

我目前正在开发一个个人的 Node.js (>=8.0.0) 项目,需要调用 C 子程序来提高执行时间。由于需要在浏览器中打开我的最终代码,因此我尝试使用 WebAssembly 来实现。

我已经使用 Emscripten 将 C 代码编译成 WebAssembly,但不知道该如何继续操作。

如果能提供任何帮助方向,将不胜感激。谢谢!

2个回答

16
你可以创建一个没有JS粘合文件的standalone.wasm文件。有人已经回答了类似的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 Instantiation: Imports argument must be present and must be an object at at process._tickCallback (internal/process/next_tick.js:188:7) at Function.Module.runMain (module.js:695:11) at startup (bootstrap_node.js:191:16) at bootstrap_node.js:612:3


虽然我几天前就找到了答案,但是你的回答帮助我更好地理解了。谢谢! - Cheran
2
出现“LinkError: WebAssembly实例化:导入#0模块=“env”函数=“__memory_base”错误:全局导入必须是数字”的错误。 - JBaczuk
该示例不适用于node 10.x和8.91以及emcc 1.38.21。与@JBaczuk相同的错误: LinkError: WebAssembly实例化:导入#0模块=“env”函数=“__memory_base”错误:全局导入必须是数字 - sven
找到了问题: test.c#include int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a+b; }Node.js 应用程序:将 memoryBase 替换为 __memory_base - sven
使用Node 8.93时,我遇到了LinkError错误:WebAssembly实例化:表导入0小于最小值2,得到了0。 - frankster

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);
});

1
有没有用C++而不是C来完成这个的方法? - user12658460
不好意思,我把C语言放在一边,转而使用Golang。Golang非常容易转换为WebAssembly。https://github.com/golang/go/wiki/WebAssemblyhttps://stdiopt.github.io/gowasm-experiments/hexy/ - Helmut Kemper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接