Install the emscripten toolchain. See instructions here
We will compile a simple c
program using emscripten which will generate
WebAssembly code. Then, in a simple web page, we will load the resulting wasm
generated file and pass it to the WebAssembly facility now found in any decent
browser. Simple as that!
Create a simple c
program:
extern void print(char *index, int length);
int main() {
print("hello!", 5);
}
Then compile it using emscripten:
emcc hello.c -s WASM=1 -Os -o hello.js
WASM=1
tells emcc
to compile to wasm
instead of the native asm.js
.
-Os
tells emcc
to strip the runtime part
(all the code that let us print, use math function, use SDL as WebGL, etc).
This will generate two files:
- hello.js: which is the WebAssembly Javascript API, which we don't need in our simple example.
- hello.wasm: the resulting assembly code.
Create a simple index.html
page.
In a script
tag, use the fetch
API to load the wasm
file and pass the
result to WebAssembly.instantiateStreaming
:
<script type="text/javascript">
const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 });
const buffer = new Uint8Array(memory.buffer);
const imports = {
env: {
memory: memory,
STACKTOP: 0,
_print: (index, size) => {
let s = "";
for (let i = index; i < index + size; ++i)
s += String.fromCharCode(buffer[i]);
console.log(s);
},
},
};
WebAssembly.instantiateStreaming(fetch('hello.wasm'), imports)
.then(obj => obj.instance.exports._main());
</script>
Note the use of the imports
object. This is an array passed to our compiled
c
code which it can callback.
Here we create a memory
object which is just a buffer shared between the
javascript
instance and the c
instance. When we call print, this is not
the actual string which is passed but the pointer itself which happens to be
the index of the string in the buffer. In the _print
function, we just
retrieve the data from the buffer and convert them to a string before printing
it.
To serve your file make sure that your web server knows the application/wasm
MIME-type. python -m http.server
do not know this type for example. You can
customize it with
your own type though.