RustでWebAssembly: Cargo編

RustでWebAssemblyを動かすのだが(これは11月5日のtest01と同様)、このときCargoを使ってみるテスト。

環境はWindows 10。

自分的プロジェクト名はtest03。

ソースなどはこちら (Github)

Cargoでプロジェクトの作成

ターミナルで以下を実行。

cargo new --lib test03

wasmのプロジェクトはライブラリ扱いになるよう。

Rustソース

Rustのソースファイルは以下のような感じ。test01と同様のadd()関数を定義する。

lib.rs

#![no_main]    // this file does not contain a main function

#[no_mangle]   // we do not want to mangle the symbol when exporting
pub extern fn add(a: i32, b: i32) -> i32 { a + b }

Cargo.tomlファイル

Cargo.tomlにビルドに必要な情報を書く。[lib]の部分を追加することになる。

Cargo.toml

[package]
name = "test03"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

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

[dependencies]

Cargoでビルド

ターミナル上で、プロジェクトのディレクトリ内で以下を実行すればデバッグビルドがなされる。

cargo build --target=wasm32-unknown-unknown

これで、以下のwasmファイルが生成される。
./target/wasm32-unknown-unknown/debug/test03.wasm

リリースビルドは

cargo build --target=wasm32-unknown-unknown --release

で可能。できるwasmファイルは次のようなもの。
./target/wasm32-unknown-unknown/release/test03.wasm

HTML/JS側

HTMLファイルとして以下のようなものを書いた。

どっちみち自分の用途ではawaitが必要なので、asyncをJS全体にかけるようにした。wasm関数の取得時のみならず、関数実行時点もasync内にないと非同期になってしまうようなので。(このあたりよくわからない。。)

test03.html

<html>
<body>

<div>add( 10, 20) = </div>
<div id = "msg">(now calculating...)</div>

<script>
(async function(){ // もう、script部分は丸ごとasyncありきで。。。

  // 画面要素のIDの取得
  let msg_id = document.getElementById( "msg");

  // WASM関数の取得
  let wasm = await WebAssembly.instantiateStreaming( fetch( "test03.wasm"), {});
  let wasm_add = wasm.instance.exports.add;

  msg_id.innerText = wasm_add( 10, 20);

})();
</script>

</body>
</html>

以下のサイトを参考にさせていただいた。
福野泰介の一日一創 RustではじめるWebAssemblyはじめのいっぽ、足し算するwasmファイルは116byte

閲覧

test01と同様、HTMLファイルをHTTPサーバーに置いてretrieveする必要があるが、VSCodeの「Go Live」でもどうぞ。

やったぜ。