stevenchucp
stevenchucp

Reputation: 104

Calling and wrapping C function in Nodejs (Emscripten)

I'm new to emscripten and web development.

Recently, I'm trying to build a node.js module based on C library. I'm testing with a simple function like int add(int a, int b). I use MODULARIZE to compile the C library to let it pass the module as a wrapped promise function instead of global Modules.

I can call the function in javascript with ccall method like how the emscripten document stated.

factory().then(instance => {
   instance.ccall('add', 'number', ['number', 'number'], [1, 1]);
});

But how can I wrap the function in a way that lets me call the function without dealing with Promises? eg.

let sum = add(1, 2);
// sum = 3;

Upvotes: 1

Views: 1390

Answers (1)

Dark-Boy-INFINITE
Dark-Boy-INFINITE

Reputation: 89

You can create a standalone wasm binary and then use WebAssembly.Instance to act as a wrapper. First create a c file with no main.

#include <emscripten/emscripten.h>

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

NOTE: You have to use EMSCRIPTEN_KEEPALIVE before every function you want to export. Then compile to standalone wasm using

$ emcc {Path to your c file } -o {The name of stand alone wasm} --no-entry

NOTE: You have to write extension in file names.

For example $ emcc abc.c -o xyz.wasm --no-entry should generate a single xyz.wasm and nothing else.

Now in your JS file, you can do

const readFileSync = require('fs').readFileSync;
const wasm_module = new WebAssembly.Instance(new 
WebAssembly.Module(readFileSync(**{Path to the .wasm file you generated}**)));

Then all or your exported functions will be available in wasm_module.exports, so you can do something like

const add = wasm_module.exports.add;
let sum = add(1, 2);
// sum = 3

UPDATE

Now node supports experimantal wasm modules. So instead of that long JS code you can just import it from .wasm file directly, like:

import * from '**{Path to .wasm file you generated}**' as wasm_module;
let sum = wasm_module.add(1, 2);
// sum = 3

NOTE: This feature is experimental so you will need to enable it explicitly. i.e. Instead of $ node script.js, use $ --experimental-wasm-modules script.js.

Upvotes: 2

Related Questions