16

I'm currently using Emscripten to compile a basic C function into JavaScript to use within a React Native project. However, when I import Module from inside React code, the Module object is empty. This occurs in both React and React Native projects.

Running index.js in my terminal with node ./index.js returns the expected result.

I'm compiling ping.c and outputting ping.js with this command:

emcc ping.c -o ping.js -s WASM=0 -s EXPORTED_FUNCTIONS='["_pingIt"]'

ping.c:

#include <stdio.h>
#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int pingIt() {
  return 1;
}

index.js:

let Module = require('./ping.js');

module.exports = Module;

I'm exporting Module from index.js and importing it into my React code.

Current behavior

// Running in React
console.log(Module); // returns {}

Expected behavior

// Running in React
console.log(Module._pingIt()); // should return 1
Chris Poe
  • 678
  • 6
  • 15
  • I'm not sure if WASM supports ES6 import syntax yet. Have you tried adding a `script` tag in your `index.html` page and accessing `Module` as a global variable? – seanulus Jan 09 '19 at 18:27
  • 1
    @seanulus my main goal is to get it to run inside a React Native project. I have disabled WASM with the `WASM=0` option in my `emcc` command. – Chris Poe Jan 09 '19 at 18:41

2 Answers2

16

I stumbled across a MODULARIZE setting in the Emscripten docs here. I edited the emcc command:

emcc ping.c -o ping.js -s WASM=0 -s ENVIRONMENT=web -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' -s MODULARIZE=1

MODULARIZE=1 being the magic bit

Now within the index.js file:

let Module = require('./ping.js'); // Your Emscripten JS output file
let pingIt = Module().cwrap('pingIt'); // Call Module as a function

module.exports = pingIt;

Now in the React component you can import pingIt from '<file-location>'; and call the function like any other pingIt().

Hope someone finds this useful! I couldn't find many examples of using Emscripten alongside React.

ravibagul91
  • 20,072
  • 5
  • 36
  • 59
Chris Poe
  • 678
  • 6
  • 15
0

I used a slightly different approach to call the ping.c function from React Native, by defining an EXPORT_NAME for the module and creating the module whenever it's appropriate in your code.

Using Emscripten emsdk:

emcc ping.c -o ping.js -s WASM=0 -s ENVIRONMENT=web -s MODULARIZE=1 -s "EXPORT_NAME='createPingModule'"

In the React Native component (App.tsx):

import createPingModule from './ping';

...

createPingModule()
  .then(module => {
    console.log('Module created!');
    let a = module._pingIt();
    console.log(a);
});
Sander
  • 161
  • 1
  • 5