⚡
【Rust】WASMにコンパイルしてDenoから呼び出す方法
Rustで書いたモジュールを Webassembly にコンパイルして Deno から呼び出して実行します。
Denoはasyncなしで、awaitが使用可能なので、Wasmの読み込みもすっきり記述することができそうです。
ポイント
- Rustでモジュールを作成する
- Webassembly にコンパイルする
- Deno から呼び出す
関連
準備
Denoのインストール
Rustのインストール
WASM関連の依存関係インストール
コンパイラ
rustup target add wasm32-unknown-unknown
GC
cargo install wasm-gc
Rustモジュールの作成
クレートの作成
以下のコマンドを実行し、wasm_deno_example
クレートを作成します。
cargo new --lib wasm_deno
cd wasm_deno
プロジェクトファイル群が生成されます。
Cargo.toml
ファイルに、以下を追記します。
[lib]
crate-type =["cdylib"]
cdylibは、RustプロジェクトをWASMのような他の言語でも使えるようにするために必要です。
Rustプログラムを書く
今回は src/lib.rs
に以下のシンプルな関数を書きました。
src/lib.rs
#[no_mangle]
pub extern "C" fn square(x: u32) -> u32 {
x * x
}
-
#[no_mangle]
をつけるとマングリング[1]されなくなります。 - externは、他の言語(ここではDeno)から呼び出すために必要な宣言です。
WASMにコンパイルする
以下のコマンドでコンパイルします。
cargo build --target wasm32-unknown-unknown
出力されたファイルをGCツールにかけることで、ファイルサイズを小さくすることができます。
wasm-gc target/wasm32-unknown-unknown/debug/wasm_deno.wasm
Denoから呼び出す
main.ts
ファイルを作成します。
以下のようにWASMを読み込んで実行するコードを記述します。
main.ts
// 1.Wasmをロード
const wasmCode = await Deno.readFile("./target/wasm32-unknown-unknown/debug/wasm_deno.wasm");
// 2.ロードしたファイルからWasmモジュールを作成
const wasmModule = new WebAssembly.Module(wasmCode);
// 3.関数を使用できるようモジュールのインスタンスを作成
const wasmInstance = new WebAssembly.Instance(wasmModule);
const { square } = wasmInstance.exports;
console.log(square(1)); // 1
console.log(square(2)); // 4
console.log(square(3)); // 9
console.log(square(4)); // 16
実行します。
deno run --allow-read main.ts
# Check file:///var/www/html/main.ts
# 1
# 4
# 9
# 16
WASMのモジュールが実行され、結果が出力されました。
参考
-
マングリング: ざっくり言うと、関数名や変数名がエンコードされたりなどして変わること。 ↩︎
Discussion