I am trying out a simple example to call a C function compiled to .wasm with JavaScript.
This is the counter.c
file:
#include <emscripten.h>
int counter = 100;
EMSCRIPTEN_KEEPALIVE
int count() {
counter += 1;
return counter;
}
I compiled it using emcc counter.c -s WASM=1 -o counter.js
.
My main.js
JavaScript file:
Module['onRuntimeInitialized'] = onRuntimeInitialized;
const count = Module.cwrap('count ', 'number');
function onRuntimeInitialized() {
console.log(count());
}
My index.html
file only loads both .js files in the body, nothing else:
<script type="text/javascript" src="counter.js"></script>
<script type="text/javascript" src="main.js"></script>
It works fine / prints 101 to the console, but when I move the counter.c
file to a wasm
subdirectory, recompile it with emscripten and update the script
tag to src="wasm/counter.js"
, the counter.js
script tries to load counter.wasm
from the root directory instead of the wasm
subdirectory and I get the error:
counter.js:190 failed to asynchronously prepare wasm: failed to load wasm binary file at 'counter.wasm'
I did some research, but I didn't find any way to tell emscripten to let the generated .js file load the .wasm from the same subdirectory.
As explained by ColinE in the other answer, you should look at the integrateWasmJS() function generated by the emcc compiler (counter.js). The body of that function has changed recently and now it looks like this:
function integrateWasmJS() {
...
var wasmBinaryFile = 'counter.wasm';
if (typeof Module['locateFile'] === 'function') {
...
if (!isDataURI(wasmBinaryFile)) {
wasmBinaryFile = Module['locateFile'](wasmBinaryFile);
}
...
}
}
If this is the case, then you should add a "locateFile" function to the global Module variable. So in your HTML, you could add the following snippet before importing the counter.js file:
<script>
var Module = {
locateFile: function(s) {
return 'wasm/' + s;
}
};
</script>
If you look at the generated 'loader' file that emscripten creates, it has an integrateWasmJS
function as follows:
function integrateWasmJS(Module) {
var method = Module['wasmJSMethod'] || 'native-wasm';
Module['wasmJSMethod'] = method;
var wasmTextFile = Module['wasmTextFile'] || 'hello.wast';
var wasmBinaryFile = Module['wasmBinaryFile'] || 'hello.wasm';
var asmjsCodeFile = Module['asmjsCodeFile'] || 'hello.temp.asm.js';
...
}
You can see that the wasmBinaryFile
indicates the location of the binary. If it is not set it provides a default.
It looks like you should be able to override this in your main.js
file as follows:
Module['wasmBinaryFile'] = 'wasm/counter.wasm';
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With