こんにちは、コバヤシです。
WebAssemblyって知っていますか?
何かと目にする機会も多くなってきたので、今更感も強いですがRustを使ってWebAssemblyを試してみたいと思います。
WebAssemblyとは
WebAssemblyはWebブラウザーが実行できるバイナリー形式の言語です。
Rustなどの言語で書かれたプログラムをコンパイルして実行します。
コンパイル済みなのでJavaScriptより高速に動作。
現在のところJavaScriptを置き換えるものではなく互いにサポートし合うというのが狙いのようです。
使い所としては、画像やビデオの編集などの計算量の多い処理をWebAssemblyで書かれたプログラムで処理させるなどが考えられます。
Rustとは
Rustは2006年に開発が始まった新しいオープンソースのプログラミング言語です。
高い安全性や高パフォーマンスからC/C++に置き換わる言語として注目されおり、
MicrosoftはWindowsの開発にRustを採用していることを公表しています。
今回はこのRustを使ってWebAssemblyを作成していきます。
Rustのインストール
Macの環境でインストールしていきます。
brew install rustup-init
brewで簡単にインストール出来ます。
インストールが出来たら初期化します。
rustup-init warning: it looks like you have an existing installation of Rust at: warning: /usr/local/bin warning: rustup should not be installed alongside Rust. Please uninstall your existing Rust first. warning: Otherwise you may have confusion unless you are careful with your PATH warning: If you are sure that you want both rustup and your already installed Rust warning: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes warning: or pass `-y' to ignore all ignorable checks. error: cannot install while Rust is installed
何やらエラーがでました。
Rustが入っているというエラーなのでRustを削除します。
(以前お試しで入れたような記憶が。。)
brew uninstall rust
アンインストールが出来たら再度実行します。
brew uninstall rust 1) Proceed with installation (default) 2) Customize installation 3) Cancel installation >1
初期化が終わったら設定を反映します。
source "$HOME/.cargo/env"
インストールできたのか確認します。
rustup --version rustup 1.25.2 (2023-02-01) info: This is the version for the rustup toolchain manager, not the rustc compiler. info: The currently active `rustc` version is `rustc 1.67.1 (d5a82bbd2 2023-02-07)`
無事インストール出来たようなのでプロジェクトを作成して実行してみます。
cargo new hello cd hello cargo run Compiling hello v0.1.0 (/xxxx/xxx/xxxx/xxxx/hello) Finished dev [unoptimized + debuginfo] target(s) in 0.89s Running `target/debug/hello` Hello, world!
無事に表示されました。
WebAssemblyを作成する
実際にWebAssemblyを作成していきます。
まずWebAssembly(wasm)をビルドするためのパッケージをインストールします。
※WebAssemblyのファイル形式にはwasm形式とwat形式があります。
バイナリ形式がwasm、人が読める形の中間ファイルがwat形式です
cargo install wasm-pack
プロジェクトをライブラリのプロジェクトとして作成します。
cargo new --lib hello-wasm
プロジェクトが出来たら
src/lib.rsを以下のように書き換えます。
use wasm_bindgen::prelude::*; #[wasm_bindgen] extern { pub fn alert(s: &str); } #[wasm_bindgen] pub fn say(name: &str) { alert(&format!("Hello, {}!", name)); }
「use wasm_bindgen::prelude::*;」でJavaScriptとRustを繋ぐモジュール(Rustではクレートと呼ばれる)を読み込んでいます。
externで使用したいJavaScriptの命令を記述。
pub fnで、JavaScript側から呼び出してもらう命令を記述します。
次は、ビルドですが
その前にCargo.tomlを編集して設定を書き換えます。
実際は[package]部分も書き換える必要があるのですが今回は割愛します。
[package] name = "hello-wasm" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] wasm-bindgen = "0.2" <= 追記 [lib] <= 追記 crate-type = ["cdylib"] <= 追記
targetをwebにしてビルドをします。
wasm-pack build --target web
ビルドをすると「pkg」ディレクトリが作成されるので、これをwebの公開ディレクトリに配置します。
そして、このpkgをjavascriptから読み込みます。
scriptタグでタイプをmoduleとして記述するのがミソです。
<body> <script type="module"> import init, {say} from "./pkg/hello_wasm.js"; init() .then(() => { say("World") }); </script> </body>
ページを読み込むとアラートが表示されました。
JavaScriptからRustで書いた命令が実行出来て、Rust側からJavaScriptのアラートが実行出来ています。
不思議な感じがしますが面白いですね。
まとめ
今回はアラートだけでしたが、実際はJavaScriptでは荷が重い処理をさせた時に真価が発揮されます。 今後もRustを含め勉強していきたいと思います。