Wildcardな雑記

なんか書く

RustでWebAssemblyに軽く入門した

はじめに

これはあくまで個人的な日々の記録であり備忘録です.WebAssemblyに興味があり,Rustで使えるとのことなので,使ってみました.メモを書き残しておきます.

以下の参考サイトを習っています.

やったのは,"alert"で警告ダイアログのポップアップを出すだけでJavaScriptでも書ける内容ですが,今回はそれをRustで書いたコードから生成されたwasmファイルに処理を書いていて,それをjavascriptから呼び出す感じの処理を書いています.

この記事はあくまで備忘録ですが,以下の手順でメモしています.

  1. 環境構築
  2. rustでwasmバイナリにコンパイルしたいコードを書く
  3. wasmバイナリにコンパイル
  4. webサーバを立ち上げてブラウザでアクセスしてwasmで書いた処理を実行させてみる

環境構築

まず,使ったRustとcargoのバージョンは以下です.共に1.55.0です.以下のようなコマンドで確認できます.

[~]
% rustc -V
rustc 1.55.0 (c8dfcfe04 2021-09-06)
[~]
% cargo --version
cargo 1.55.0 (32da73ab1 2021-08-23)
[~]
%

Rustで書いたコードをwasmにコンパイルする,wasm-packが必要らしいです.以下のようにcargo installで入れます.

cargo install wasm-pack

使ってみる

cargo newで"--lib"オプションをつけて,ライブラリ用のターゲットを作ります.cargo newに関するオプションの詳細は公式docから確認可能

名前はhi-wasmにしました(helloじゃなくてhiにしただけで特に意味はないです).

cargo new --lib hi-wasm

wasmにコンパイルされるコードをRustで書く

src/lib.rsにRustでWebAssemblyで実行するコードを書いてみる.

[~/Code/Project/Project_WebAssembly/hi-wasm]
% cat src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    pub fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hi, {}!", name));
}

wasm-bindgenというのが気になったのだけれど,これは"RustとJavascriptの間でやり取りする"ために必要であり,JavascriptからRustで書いたAPI(上記コードでいうgreet)を呼び出せるそうです.

このときのCargo.toml

Cargo.tomlは以下のようにする.

[~/Code/Project/Project_WebAssembly/hi-wasm]
% cat Cargo.toml
[package]
name = "hi-wasm"
version = "0.1.0"
edition = "2018"

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

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

[dependencies]
wasm-bindgen = "0.2"

Rustコードをwasmへコンパイルする

wasm-pack buildコマンドで,上記のRustのコード(src/lib.rs)をwasmにコンパイルする.参考サイトにならい,"--target web"オプションをつけた.

[~/Code/Project/Project_WebAssembly/hi-wasm]
% wasm-pack build --target web

これを機にwasm-packについて調べた

wasm-packというのを初めて使ったし,"--target web"という書き方がよく分からなかったので調べてみた.公式docを読んで知ったのが以下.

オプション 使用法(usge) 説明(description)
web Native in browser(ブラウザネイティブ?) Outputs JS that can be natively imported as an ES module in a browser, but the WebAssembly must be manually instantiated and loaded. (ESモジュールとしてブラウザにネイティブにインポートできるJSファイルを出力する.ただし,WebAssemblyはマニュアルにインスタンス化されロードされなければならない)

webオプションは,ブラウザにロードされるJSファイルを出力するという意味らしいです.

ちなみに,wasm-pack buildは以下のようなコマンドらしいです.

The wasm-pack build command creates the files neccessary for JavaScript interoperability and for publishing a package to npm. This involves compiling your code to wasm and generating a pkg folder. This pkg folder will contain the wasm binary, a JS wrapper file, your README, and a package.json file.

「"wasm-pack build"は,Javascriptとの相互運用性に必要なファイル群を作成するためのコマンドであり,また,packageをnpmで配布するためのコマンドです.これはあなたのコードをwasmへとコンパイルし,pkgフォルダを生成します.pkgフォルダはwasmバイナリ,JSラッパーファイル,そしてREADMEとpackage.jsonファイルを含んでいます.」

wasmで書いた処理をjavascriptから呼び出すwebページにアクセスしてみる

参考サイトに習い,index.htmlを作ります.pkg以下にあるhi_wasm.jsをインポートしてます.wasmで書いた処理を呼び出すjsコードみたいに書けそうですね

[~/Code/Project/Project_WebAssembly/hi-wasm]
% cat index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>hi-wasm example</title>
  </head>
  <body>
    <script type="module">
      import init, {greet} from "./pkg/hi_wasm.js";
      init()
        .then(() => {
          greet("WebAssembly")
        });
      </script>
  </body>
</html>

webサーバを立ててアクセスする

どこかで見かけた知恵ですが,pythonでwebサーバを立てると,localhost:8000からアクセスできます.

アラートボックス( "Hi WebAssembly"が出たら,ここでは成功です.(普通にjavascriptでも書けそうな処理ですが)

[~/Code/Project/Project_WebAssembly/hi-wasm]
% python3 -m http.server

f:id:aster-wildcard:20211031181725p:plain
こんな感じにアラートボックスが出た

感想と今後の展望

  • npmは慣れてなかったんだけど,python3でwebサーバを立ててもカジュアルにアクセスできるってことが分かったので,敷居が下がった.

  • チュートリアルが分かりやすくて学習に助りましたありがとう.こんな感じか,って分かった.使いこなせるようになりたい.本腰入れて公式のドキュメントとかからじっくり読もう

  • もっと勉強して使いこなせるようになりたいと思った.

参考文献

本記事はこれを実践してました.

wasm-packのコマンドについて気になったので調べるのに見ていました.