WebAssembly - Writing Programs Steps

  1. write: write program in a C/C++ runtime language (e.g. C, C++, Rust, etc)
  2. compile: compile program into WebAssembly (i.e. outputting a binary .wasm file)
  3. load & instantiate: have JavaScript to fetch and compile the .wasm binary. Then instantiate it so that JavaScript can use it
  4. using it:

Write

write example C++ code

int squarer(int num) {
	return num * num;
}

Compile

there are 2 ways to compile the C++ code into WebAssembly (NOTE: I can only get the online tool to generate a .wasm file that could be used in JavaScript):

after compilation, any C++ functions that you write will be available in WebAssembly as something called an “export.” Exports are the things that you’ll be able to interact with and use in JavaScript.

online tool compiler

IMPORTANT NOTE: as shown above, the C++ function named squarer has somehow become _z7squareri. This is because the “_Z7” prefix and “i” suffix are debug markers introduced by the C++ compiler

Load & Instantiate

now we have a WebAssembly file, let’s name it squarer.wasm

we will create 2 new files:

  • scripts.js - takes care of loading and instantiating WebAssembly file
  • index.html - includes scripts.js
2 Ways to Load & Instantiate a .wasm file

Using It

Now, just call your function and pass in an argument from the console. Try something like squarer(9) . Hit return and you’ll see 81 . It works! You’re calling a function written in C++!

IMPORTANT NOTE: make sure the function name matches with the online tool: obj.instance.exports._Z7squareri(9);

var importObject = { env: {
	'memoryBase': 0,
    'tableBase': 0,
    'memory': new WebAssembly.Memory({initial: 256}),
    'table': new WebAssembly.Table({initial: 256, element: 'anyfunc'}),
    abort: alert,
}};
 
fetch('squarer.wasm')
    .then(response => response.arrayBuffer())                    // get the .wasm bytes into a typed array or ArrayBuffer
    .then(bytes => WebAssembly.instantiate(bytes, importObject)) // compile & instantiate WebAssembly.Module
    .then(obj => {
        var output = obj.instance.exports._Z7squareri(9);
        console.log(output);
    });

Example WebAssembly Object Function Calls

WebAssembly.instantiateStreaming(fetch('myModule.wasm'), importObject)
	.then(obj => {
  		// Call an exported function:
  		obj.instance.exports.exported_func();
 
  		// or access the buffer contents of an exported memory:
  		var i32 = new Uint32Array(obj.instance.exports.memory.buffer);
 
 		// or access the elements of an exported table:
 	 	var table = obj.instance.exports.table;
  		console.log(table.get(0)());
	})