12

I am currently working on a personal Node.js (>=8.0.0) project which requires me to call C subroutines (to improve execution time). I am trying to use WebAssembly to do this since I need my final code to be compatible when opened in a browser.

I have used Emscripten to compile C code into WebAssembly, and do not know how to proceed after this.

Any help in the right direction would be great. Thanks!

2 Answers 2

17

You can build a .wasm file (standalone) without JS glue file. Someone has answered the similar question.

Create a test.c file:

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

Build the standalone .wasm file:

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

Use the .wasm file in Node.js app:

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

The key part is the second parameter of WebAssembly.instantiate(). Without it, you will get the error message:

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

Sign up to request clarification or add additional context in comments.

5 Comments

Although I figured out the answer a couple of days ago, your answer helped me understand better. Thanks!
Getting LinkError: WebAssembly Instantiation: Import #0 module="env" function="__memory_base" error: global import must be a number
The example don't work with node 10.x and 8.91. and emcc 1.38.21. Same error as @JBaczuk: LinkError: WebAssembly Instantiation: Import #0 module="env" function="__memory_base" error: global import must be a number
Found the problem: test.c #include <emscripten/emscripten.h> int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a+b; } Node.js app: replace memoryBase with __memory_base
With node 8.93 I get LinkError: WebAssembly Instantiation: table import 0 is smaller than minimum 2, got 0
1

Thanks @sven. ( translate only )

test.c:

#include <emscripten/emscripten.h>

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

compiling:

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 Comments

Is there any way to do this with c++ instead of c?
Excuse me. I left C aside and went to Golang. Golang becomes webassembly very easy github.com/golang/go/wiki/WebAssembly stdiopt.github.io/gowasm-experiments/hexy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.