DEV Community

Hasan Yousef
Hasan Yousef

Posted on

Rust + WASM using bindgen

This is an advance topic using bindgen, as second step to my previouse post

  1. Create project folder utils2
  2. cd to this folder
  3. from this folder create your lib:
// install rust if not yet done
// curl https://sh.rustup.rs -sSf | sh
mkdir utils2
cd utils 2
cargo init --lib

// Or it can be created in one line as:
cargo new utils2 --lib
cd utils2
  1. make the default toolchain as nightly as wasm is only supported in nightly now:
rustup override set nightly
// Add was32 target if not yet installed
rustup target add wasm32-unknown-unknown --toolchain nightly

note:
Platforms are defined by their Target Triplet that is: machine-vendor-operatingsystem:

  1. Machine / the name of the CPU family/model: wasm32,
  2. The vendor: no specific, so it is unknown,
  3. The operating system name: no specific, so it is unknown.

  4. Create npm package file by running:

npm init

the above will create package.json.

  1. Install webpack npm requirements, the node_modules folder will be created:
// brew install node
npm install -D webpack webpack-cli webpack-dev-server

the above will alter the package.json and make it loos something like::

{
  "name": "utils2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.27.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10"
  }
}
  1. Create domUtils.js, index.html, index.js and webpack.config.js files, so that the structure be as below:
// if you need to install tree, it can be done by
// brew install tree
$ tree .
.
├── Cargo.lock
├── Cargo.toml
├── domUtils.js
├── index.html
├── index.js
├── package.json
├── src
│   └── lib.rs
└── webpack.config.js
  1. Open the folder files in your idea, and update them, as shown in point #11
$ idea .
  1. Build the rust wasm lib using wasm-pack as:
// cargo install wasm-pack
wasm-pack build
// this will create the standard target folder, and additional folder called pkg
// the pkg folder tree is:
├── pkg
│   ├── utils2.d.ts
│   ├── utils2.js
│   ├── utils2_bg.d.ts
│   └── utils2_bg.wasm
  1. Run the server as:
npx webpack-dev-server
  1. The files:

Cargo.toml

[package]
name = "utils2"
version = "0.1.0"
authors = ["Hasan Yousef"]
edition = "2018"

[dependencies]
wasm-bindgen = "0.2.29"

[lib]
crate-type = ["cdylib"]

domUtils.js

export const appendStringToBody = (value) => {
  const text = document.createTextNode(value);
  document.body.appendChild(text);
}

libs.rs:

use wasm_bindgen::prelude::*;

// Define the JS function signature
#[wasm_bindgen(module = "../domUtils")]
extern {
    fn appendStringToBody(s: &str);
}

#[wasm_bindgen]
pub fn run(my_text :&str) {
    // Call the JavaScript function
    #[allow(unused_unsafe)]
    unsafe {
        appendStringToBody(my_text);
    }
}

webpack.config.js

const path = require("path");

module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.js",
  },
  mode: "development"
};

index.js

import("./pkg/my_app").then(wasmModule => {
  wasmModule.run("hi there");
});

index.html

<!DOCTYPE html>
<html>
<head>
    <script src="./index.js"></script>
    <head>
<body></body>
<html>

Top comments (1)

Collapse
 
matthieudesprez profile image
Matthieu Desprez

Thanks for this article !

For those who use a more recent version of wasm-bindgen, you have to replace module by raw_module in lib.rs (see github.com/rustwasm/wasm-bindgen/i... for more information).