Skip to content

Instantly share code, notes, and snippets.

@kripken
Last active September 29, 2024 17:39
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>
@st-patrick
Copy link

I had the same problem as @dotaheor and the solution suggested by @william8000 worked for me! (Chrome as well as Firefox)

@gutenye
Copy link

gutenye commented Mar 19, 2019

Confirmed, needs extra flag by @yard

@sudheer5
Copy link

sudheer5 commented Apr 25, 2019

Hi,
I tried to get the debugging of c file in the browser using the following code.

'C' code:
int doubler(int x) {
return 2 * x;
}

compilation code:
emcc hello_world.c -g4 -s WASM=1 -s SIDE_MODULE=1 -s "EXPORTED_FUNCTIONS=['_doubler']" -o hello_world.wasm -g --source-map-base http://localhost:6931/

error:
Unknown option '--all-features'
shared:ERROR: 'D:/GitHub/emsdk/clang/e1.38.30_64bit/binaryen\bin\wasm-as hello_world.wast -o hello_world.wasm --all-features --disable-bulk-memory -g --source-map=hello_world.wasm.map --source-map-url=http://localhost:6931/hello_world.wasm.map' failed (1)

any help would be appreciated.
thanks

@wuxulome
Copy link

My output is {"exports":{}} too, but if add code: console.log(wa.exports._doubler(xx));, I can also get the right results in console.

@jalamari2018
Copy link

jalamari2018 commented Sep 19, 2019

I tried all proposed solutions but none of them works for me.
I don't have any issue when I write .wat files and use wat2wasm tool to generate .wasm files.
the problem happens only when I use emscripten to generate WebAssembly code.

@kripken
Copy link
Author

kripken commented Sep 19, 2019

Emscripten is adding proper support for emitting standalone wasm now, see emscripten-core/emscripten#9461

@kripken
Copy link
Author

kripken commented Nov 22, 2019

More details on emscripten's standalone wasm support: https://v8.dev/blog/emscripten-standalone-wasm

@iiic
Copy link

iiic commented Feb 27, 2020

Why it's there a _ preffix ? It's breaking function for me, it works well after I remove it. Was it something in the past versions ? ( used emcc 1.39.8 ; clang version 11.0.0 )

@kripken
Copy link
Author

kripken commented Feb 27, 2020

@iiic The old fastcomp backend added _ prefixes on the wasm exports. The new upstream backend (like in the version you use) doesn't, which can be noticeable if you access the exports directly.

@cloudwheels
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

@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