Codementor Events

Simple Rust + WASM example

Published Mar 23, 2019
  1. Install rust
$ brew install rustup
$ rustup-init
  1. Set default toolchain as nightly
$ rustup default nightly
  1. Ass wasm target
$ rustup target add wasm32-unknown-unknown
  1. Install wasm-gc tool to remove all unneeded exports, imports, functions, and so on from the generated WebAssembly module.
$ cargo install wasm-gc
  1. Instal https to runs a web server, serving static files from the current directory
$ cargo install https
  1. Create rust app, and open its files with your IDE (I'm using idea)
$ cargo new --lib utils
$ cd utils
$ idea .

7.Define the rust CDI lib type in the cargo.toml:

[package]
name = "utils"
version = "0.1.0"
authors = ["Hasan Yousef <hasan.ajsf@gmail.com>"]
edition = "2018"

[dependencies]

[lib]
crate-type =["cdylib"]
  1. Define the extern function:
pub extern fn add_one(x: u32) -> u32 { x + 1
}

The extern keyword is needed to create an interface, so that this function can be invoked from other languages. The no-mangle annotation to tell the Rust compiler not to mangle the name of this function.
2. Build the wasm file:

$ cargo build --target wasm32-unknown-unknown --release
  1. Run the wasm-gc to optimize the wasm file:
$ wasm-gc target/wasm32-unknown-unknown/release/utils.wasm -o utils.gc.wasm
  1. Create the index.html file, and call the wasm module through javascript:
<html>
<head>
<script> WebAssembly.instantiateStreaming(fetch("utils.gc.wasm")) .then(wasmModule => { const result = wasmModeult.instance.exports.add_one(3); const text = document.createTextNode(result); document.body.appendChild(text); });
</script>
<head>
<body></body>
<html>

Using instantiateStreaming instead, we can stream, compile, and instantiate a WebAssembly module in one go.
5. Run the static file server:

$ http
  1. Open your browser at: localhost:8000

ADVANCE

If you want to interact with JavaScript function, you need to:

  1. Define these functions signature in the rust file
  2. Define a bridge/wrapper in the javascript file between these functions

So, if want to call the javascript alert and another function, let's say, addOne, then the above main.rs and index.html files will be as below:

main.rs:

extern { fn addOne(x: u32); fn alert(x: u32);
} pub extern fn add_one(x: u32) { unsafe { addOne(x); alert(x); }
}

index.html

<html> <head> <script> const addOne = (number) => { const text = document.createTextNode(number + 1); document.body.appendChild(text); } const importObject = { env: { addOne: addOne, alert: alert, } }; WebAssembly.instantiateStreaming(fetch("utils.gc.wasm"), importObject) .then(wasmModule => { const result = wasmModule.instance.exports.add_one(5); }) </script> <head> <body></body>
<html>

For using bindgen, kindly see my other post

Discover and read more posts from Hasan Yousef
get started
post commentsBe the first to share your opinion
Show more replies