概要
RustもWebAssemblyもほぼわからない筆者が、MDNのRustからWebAsemblyにコンパイルするチュートリアルをゆっくり理解しながら記録を残す記事です。
Rustのインストール
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source "$HOME/.cargo/env"
$ rustc --version
rustc 1.65.0 (897e37553 2022-11-02)
以下のことを実施しました。
- rustupで最新の安定版のRustをインストールする
- 新しいRustのバージョンに更新する
- ローカルにインストールされたドキュメントを開く
- 「Hello, world!」プログラムを書き、rustcを直接使って実行する
- Cargoにおける習慣に従った新しいプロジェクトを作成し、実行する
VSCodeにRust用のextensionをインストール
Rustのextensionはdeprecatedでした。
代わりに、rust-analyzer extensionをインストールしました。
また、Cargo.tomlを編集するようにBetter TOMLをインストールしました。
WebAssemblyパッケージのビルド
プロジェクトの準備
cargo new
で新しいプロジェクトを作成しますが、その際に --lib
オプションを指定しています。
これはcargoが用意してくれるライブラリ作成用のテンプレートプロジェクトを作成してくれているようです。
$ cargo new --help
--lib Use a library template
$ cargo new --lib hello-wasm
一度作られたプロジェクトを見てみます。
$ tree .
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── lib.rs
└── target
-
Cargo.toml
Cargの設定のマニフェストファイルで、tomlで記述する。
別のパッケージへの依存等を記載する。 -
Cargo.lock
Cargo.lockはCargoの最新コミットを取得して、最初にビルドする際にその情報を書き込んだものでパッケージのバージョン等を管理する。 -
lib.rs
Rustのコードを記述するファイル。 -
target
コンパイルされた実行ファイルが格納されるディレクトリ。
Rustを書いていく
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
use wasm_bindgen::prelude::*;
wasm_bindgen::prelude
モジュールにあるものをすべてインポートしている。
wasm-bindgenを利用することで、JavaScript/wasmが文字列、JavaScriptオブジェクト、クラスなどと通信できるようにするためのプロジェクト。RustでJavaScriptのクラスを定義したり、JavaScriptから文字列を受け取ったり、返したりすることができます。
use
キーワードを使用することで、指定したパッケージの要素がローカルにあるかのように呼び出すことができます。
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[ ] の内側は「アトリビュート」と呼ばれ、次に来る文を何らかの形で修飾します。この場合、その文は外部で定義された関数を呼び出したいことを Rust に伝える extern です。アトリビュートは「wasm-bindgen はこれらの関数を見つける方法を知っている」ということを意味しています。
extern
はC言語ライブラリなどのその他の言語ライブラリを呼び出すことができます。ここでは、JavaScriptによって提供されるalert関数です。
JavaScript関数を呼び出したいときは、いつでもこのファイルに追加すれば、wasm-bindgenがセットアップを助けてくれる。
pub
キーワードを付けることによって、下のgreet関数でアクセスできるようになります。
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
Rustの関数定義は、fn
キーワードによって始まります。
greetという名前の関数に対して、nameという引数を受け取ります。 &str
は文字列を表す型です。