Skip to content

Instantly share code, notes, and snippets.

@kripken
Last active January 17, 2024 12:15
Show Gist options
  • Save kripken/59c67556dc03bb6d57052fedef1e61ab to your computer and use it in GitHub Desktop.
Save kripken/59c67556dc03bb6d57052fedef1e61ab to your computer and use it in GitHub Desktop.
Standalone WebAssembly Example

Standalone WebAssembly Example

Build hello_world.c using

emcc hello_world.c -Os -s WASM=1 -s SIDE_MODULE=1 -o hello_world.wasm

(make sure to use latest Emscripten incoming). That creates a WebAssembly dynamic libraryhello_world.wasm. You can then run hello_world.html in your browser, which loads and uses it.

More details: https://github.com/kripken/emscripten/wiki/WebAssembly-Standalone

int doubler(int x) {
return 2 * x;
}
<html>
<head>
<script>
// Check for wasm support.
if (!('WebAssembly' in window)) {
alert('you need a browser with wasm support enabled :(');
}
// Loads a WebAssembly dynamic library, returns a promise.
// imports is an optional imports object
function loadWebAssembly(filename, imports) {
// Fetch the file and compile it
return fetch(filename)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
// Create the imports for the module, including the
// standard dynamic library imports
imports = imports || {};
imports.env = imports.env || {};
imports.env.memoryBase = imports.env.memoryBase || 0;
imports.env.tableBase = imports.env.tableBase || 0;
if (!imports.env.memory) {
imports.env.memory = new WebAssembly.Memory({ initial: 256 });
}
if (!imports.env.table) {
imports.env.table = new WebAssembly.Table({ initial: 0, element: 'anyfunc' });
}
// Create the instance.
return new WebAssembly.Instance(module, imports);
});
}
// Main part of this example, loads the module and uses it.
loadWebAssembly('hello_world.wasm')
.then(instance => {
var exports = instance.exports; // the exports of that instance
var doubler = exports._doubler; // the "doubler" function (note "_" prefix)
// now we are ready, set up the button so the user can run the code
var button = document.getElementById('run');
button.value = 'Call a method in the WebAssembly module';
button.addEventListener('click', function() {
var input = 21;
alert(input + ' doubled is ' + doubler(input));
}, false);
}
);
</script>
</head>
<body>
<input type="button" id="run" value="(waiting for WebAssembly)"/>
</body>
</html>
@mahaidong
Copy link

I confirm I got this working by removing the "_" prefix to the function name in the html file line 38, and EXPORTED_FUNCTIONS flag for the compiler, i.e.
var doubler = exports.doubler;
emcc hello_world.c -Os -s WASM=1 -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["doubler"]' -o hello_world.wasm

cool

@frank-pian
Copy link

frank-pian commented Apr 20, 2023

I am using emcc 3.1.35. It's changed again. Do not remove the "_" in front of EXPORTED_FUNCTIONS
var doubler = exports.doubler;
emcc hello_world.c -Os -s WASM=1 -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["_doubler"]' -o hello_world.wasm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment