はじめに
本連載では、Webフロントエンド開発において注目されているバイナリ形式のプログラムファイルWebAssemblyを、Rustで実装して活用する方法を説明しています。前回記事では、円周率を計算するプログラムをRust/WebAssemblyで実装してJavaScriptの処理と比較することで、WebAssemblyの高速動作を示しました。
より本格的な処理をRust/WebAssemblyで実装していくには、JavaScriptとの間でさまざまなデータをやり取りする必要が生じてきます。そこで本記事では、Rust/WebAssemblyとJavaScriptとの間でデータを交換して処理する方法を説明します。
対象読者
- 動的なWebページにさらなる速度を求める方
- RustやWebAssemblyの概要を知りたいフロントエンドエンジニアの方
- 大きなデータをRust/WebAssemblyで処理させたい方
必要な環境
本記事のサンプルコードは、以下の環境で動作を確認しています。
- Windows 10 64bit版
- Microsoft Edge 105.0.1343.53
- rustup 1.25.1
- cargo 1.64.0
- wasm-pack 0.10.3
- Node.js v16.17.1 64bit版
今回のサンプルコードでは、WebAssemblyをビルドするRustのプロジェクトの内部に、WebAssemblyを参照するWebページのプロジェクト(wwwサブフォルダー)を含めています。プロジェクトを実行するには「wasm-pack build」コマンドでWebAssemblyをビルド後、wwwサブフォルダーで「npm install」コマンドを実行してライブラリーをインストールし、「npm run start」コマンドでプログラムを実行します。実行内容はWebブラウザーで「http://localhost:8080」を表示して確認できます。プロジェクトの生成法については、過去記事も参考にしてください。
データ交換の鍵を握るwasm_bindgenとは
最初に、文字列や数値をRust/WebAssemblyとJavaScriptとで交換する処理を説明します。図1は、本連載の初回記事でも説明した、Rust/WebAssemblyの処理でJavaScriptのダイアログを表示する例です。プログラムを実行すると「Hello, p001-basic!」というダイアログ(alert)が表示されます。
図1のサンプルで、Rustの実装はリスト1の通りです。
// JavaScriptのメソッドを実行 ...(1) #[wasm_bindgen] extern { fn alert(s: &str); } // JavaScriptにメソッドをエクスポート ...(2) #[wasm_bindgen] pub fn greet() { alert("Hello, p001-basic!"); }
(1)はexternを付与して、JavaScriptのalertメソッドをRustから呼び出す記述です。(2)のgreetメソッドは、(1)のalertメソッドを呼び出す処理です。ここでpubは、処理をJavaScript側に公開することを表します。各メソッドに付与された「#[wasm_bindgen]」で、Rust/WebAssemblyとJavaScriptとのデータ交換を指定できます。
JavaScript側(リスト2)では、(1)でWebAssemblyをインポートして、(2)でリスト1(2)のgreetメソッドを実行します。
// Rustで実装したWebAssemblyをインポート ...(1) import * as wasm from 'p001-basic'; // WebAssemblyのgreetメソッドを実行 ...(2) wasm.greet();