Reputation: 486
I've compiled a C library with Emscripten and written JS that interacts with it correctly in an interactive Node.js shell:
// script compiled by Emscripten
const _smaz = require("./_smaz");
var out_heap = _smaz['_malloc'](encoded.length * 8);
...
However, the _malloc
fails when the function is called immediately within my app:
TypeError: Cannot read property 'apply' of undefined
at Object.a._malloc
Even adding a 100ms setTimeout
solves the problem. Looks like the compiled Emscripten stuff loads asynchronously and functions can't be used immediately.
What's the correct way to handle this? The Emscripten docs suggest adding a Module['onRuntimeInitialized']
function once my "page" is loaded, but I'm not sure where that should go in a server-side Node.js app or whether it applies at all.
Here's how I'm compiling:
emcc smaz.c -O2 -o _smaz.js --closure 1 -s EXPORTED_FUNCTIONS="['_smaz_compress', '_smaz_decompress']" -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]'
Upvotes: 0
Views: 1041
Reputation: 486
Turns out there are two emcc
compiler options to disable the asynchronous startup/loading behaviour: -s BINARYEN_ASYNC_COMPILATION=0
and -s SINGLE_FILE=1
. This solves the problem for me.
From the related GitHub issue:
In general emscripten tries to do startup asynchronously for wasm, because it's what browsers can best optimize, and worse, Chrome currently has a limitation on the size of synchronous compilations (hopefully will be fixed soon). But you can force sync compilation with
-s BINARYEN_ASYNC_COMPILATION=0
.That still leaves fetching the wasm binary file. By default we fetch it asynchronously, but if you have a way to get it yourself before, you can set it on
Module['wasmBinary']
and we will just use that synchronously. Alternatively, #5296 will add an option to embed that file, making it available synchronously.
Upvotes: 1