03 Webassembly basics

Build & Run some code!

Declaring a function in Rust

Short Rust introduction

Basic callable function

                
                    #[no_mangle]
                    pub extern "C" fn add_one(x: i32) -> i32 {
                        x + 1
                    }
                
                
                
                    #[no_mangle]
                
                
  • Prevent compiler to remove function
  • Prevent compiler from renaming function
                
                    pub extern "C"
                
                
  • Public callable block
  • We assume it will be called by a C compiled target
                
                    fn add_one(x: i32) -> i32
                
                
  • Function declaration with name "add_one"
  • One parameter which is a 32-bit integer
  • Returning a 32-bit integer
                
                    {
                        x + 1
                    }
                
                
  • No need for explicit return statement
  • Last expression gets returned

Webassembly Studio

  • Online IDE
  • No compiler installation
  • Build & run in your browser 😍

Try it out

https://webassembly.studio wasm studio create project assistant

Check out the files

  • main.html
  • main.js
  • main.rs

Build & Run

wasm studio toolbar

Exercise Time

https://webassembly.studio

Instantiation

Webassembly.instantiate

                
                    fetch('../out/main.wasm')
                        .then(response => response.arrayBuffer())
                        .then(bytes => WebAssembly.instantiate(bytes))
                
                

Webassembly.instantiateStreaming

                
                    WebAssembly
                        .instantiateStreaming(fetch('../out/main.wasm'))
                        .then(instance => /* do something */);
                
                

Webassembly.instantiateStreaming

  • Better performance than instantiate
  • No conversion to ArrayBuffer
  • Fetch, compile and instantiate in one step
  • Not yet supported in Safari

Import Object

                
                    instantiate(sourceBuffer, importObject);
                    instantiateStreaming(source, importObject);
                
                

Import Object

  • Pass JS object to wasm
  • Same amount of types as last example
  • Call passed functions from wasm

Call JS functions from Rust

JS

                
                    const importObject = {
                        env: {
                            logResult(result) {
                                console.log(result);
                            },
                        }
                    }
                    ...
                    WebAssembly.instantiate(bytes, importObject)
                    ...
                
                

Rust extern block

                
                    extern {
                        fn logResult(i: i32);
                    }
                
                

Rust call

                
                    #[no_mangle]
                    pub extern "C" fn add_one(x: i32) {
                        unsafe {
                            logResult(x + 1);
                        }
                    }
                
                

unsafe

  • Usually we only write safe Rust code
  • Function is unknown at compile-time

Exercise Time

  • Define and call the logResult function
https://webassembly.studio

Resources

Questions?