Open5

WebAssembly(Rust)入門

泡沫京水泡沫京水

WebAssemblyとは

「Web上でネイティブアプリばりの高速処理ができるようにバイナリコードを実行する仕組み」
であるとざっくりとした認識で今はOKとします。

より深く知りたい人は、見出しの青い文字がリンクになっているので、リンク先のMDN docsのページを読んでいただければと思います。

泡沫京水泡沫京水

開発環境を整えよう

Rustの導入(devcontainerを使う)

DevContainerは

  • devcontainer.json
  • Dockerfile
  • compose.yaml

などを記述して、それを使って環境構築をするのだが、書くのがめんどくさかったので
https://github.com/Harurow/docker-playground-rust/tree/main
このリポジトリをクローンして使うことにする

Rustのライブラリプロジェクト(WebAssemblyを書くプロジェクト)を作成

cargo new --lib [library-name]

wasm-packwasm-bindgenを導入

cargo install wasm-pack && cargo add wasm-bindgen

コードを書く

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

ビルドする

wasm-pack build --target web

出力されたファイルについて

  • [library-name]_bg.wasm
    WebAssembly本体

  • [library-name]_bg.wasm.d.ts
    Rustで定義した関数のプロトタイプ宣言があるファイル

  • [library-name].d.ts
    Webブラウザ上にあるWebAssemblyを扱うAPIの形式に合わせた型定義ファイル

  • [library-name].js
    これもWebブラウザ上にあるWebAssemblyを扱うAPIの形式に合わせたjsファイル
    wasm内の、Rustで定義したい関数を呼び出す文があるのと、WebAssemblyに関するWebブラウザのAPIを使っているところを見ると、実際のところ触るファイルはこれなんじゃないか

実際に使う

<script type="module">
import init,{add} from "./pkg/[library_name].js"
init().then(() => {console.log( add(1,3) )})
</script>

すると、DeveloperToolのConsoleに4と表示される

泡沫京水泡沫京水

ステップアップ(DOM操作)

web-sysを導入

cargo add web-sys

コードを書く

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn draw() {
    let window = web_sys::window().unwrap();
    // web_sys::window()はOption<Window>を返すのでunwrap()で取り出す
    let document = window.document().unwrap();
    // window.document()はOption<Document>を返すのでunwrap()で取り出す


    let canvas_el_unwrap = document.get_element_by_id("canvas").unwrap();
    // document.get_element_by_id()はOption<Element>を返すのでunwrap()で取り出す
    let canvas: web_sys::HtmlCanvasElement = canvas_el_unwrap.dyn_into()::<web_sys::HtmlCanvasElement>.unwrap();
    // dyn_into()で型変換を行う

    let context_unwrap = canvas.get_context("2d").unwrap().unwrap();
    // canvas.get_context()はOption<Result<CanvasRenderingContext2d, JsValue>>を返すのでunwrap()で取り出す
    let context: web_sys::CanvasRenderingContext2d = context_unwrap.dyn_into()::<web_sys::CanvasRenderingContext2d>.unwrap();

    context.move_to(300.0, 0.0);
    context.begin_path();
    context.line_to(0.0, 600.0);
    context.line_to(600.0, 600.0);
    context.line_to(300.0, 0.0);
    context.close_path();   
    context.stroke();
    context.fill();
    Ok(())
}   

以下の14Pに記載されているコードを少し改変したもの

Smith, E. (2023). RustとWebAssemblyによるゲーム開発─安全・高速・プラットフォーム非依存のWebアプリ開発入門─ (初版). 株式会社オライリー・ジャパン.

https://www.oreilly.co.jp/books/9784814400393/

実際に運用する

泡沫京水泡沫京水

画像処理をしてみよう

imageを導入

コードを書く

実際に運用する

泡沫京水泡沫京水

部分導入から、全体的なものへ

Yewを使う

コードを書く

実際に運用する