その他

RustでWebAssemblyを書いてDenoで実行する🦕🦀

その他
この記事は約4分で読めます。

はじめに

Deno が盛り上がって来ているように見えます。🦕

Denoはasyncなしで、awaitが使用可能なので、Wasmの読み込みもすっきり記述することができそうです。

興味をそそられたので、早速やってみます。

ちなみに、 Deno環境は学習も兼ねてさっそくDockerでコンテナ化しました。

👋コンテナ上でDeno環境を試す場合は、以下からどうぞ。
【Docker入門】Deno環境をDockerで構築する🐳🦕

※以下はDockerを使用しない例です

Denoのインストール

以下公式を参照。🦕
https://deno.land/

Rustupのインストール

以下のコマンドを実行することで、Rustとそれに関わるツールセットをインストールします。

curl https://sh.rustup.rs -sSf | sh

Rustコマンドを使用するためのパスを通します。

source $HOME/.cargo/env

Wasmのインストール

コンパイラのインストール

rustup target add wasm32-unknown-unknown

GCをインストール

cargo install wasm-gc

Docker環境の場合、gccというツールがない!と怒られる場合があります。
その場合は、以下のコマンドでインストールします。

apt-get -qq -y install gcc

クレートとワークスペースの作成

以下のコマンドを実行し、wasm_deno_exampleクレートを作成します。
(Rustではライブラリのパッケージのことをクレートと呼びます ⚙)

cargo new --lib wasm_deno
cd wasm_deno

プロジェクトファイル群が生成されます。
Cargo.tomlファイルに、以下を追記します。

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

cdylibは、Rustプロジェクトをwasmのような他の言語でも使えるようにするために必要です。

Rustプログラムを書く

今回はsrc/lib.rsに以下のシンプルな関数を書きました。

#[no_mangle]
pub extern "C" fn square(x: u32) -> u32 {
    x * x
}
  • #[no_mangle]をつけるとマングリング*1されなくなります。
  • externは、他の言語(ここではDeno)から呼び出すために必要な宣言です。

*1 マングリング: ざっくり言うと、関数名や変数名がエンコードされたりなどして変わること。

RustからWasmにコンパイルする

以下のコマンドでコンパイルします。

cargo build --target wasm32-unknown-unknown

出力されたファイルをGCツールにかけることで、ファイルサイズがガッツリ小さくなります。

wasm-gc target/wasm32-unknown-unknown/debug/wasm_deno.wasm

Denoから呼び出す🦕

main.tsファイルを作成し、以下のようにWasmを呼び出します。

// 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));
console.log(square(2));
console.log(square(3));
console.log(square(4));

あとは実行するだけ!

deno run --allow-read main.ts
# Check file:///var/www/html/main.ts
# 1
# 4
# 9
# 16

Denoは標準でファイル、ネットワーク、環境変数等にアクセスすることができないセキュアな設定になっています。
ファイルの読み取りをを許可するには--allow-readオプションを付与して実行します。

まとめ

簡単なWasmを作成し、Denoで実行できました!🦕🦀

参考

https://dev.to/lampewebdev/writing-webassembly-in-rust-and-runing-it-in-deno-144j
https://doc.rust-jp.rs/book/second-edition/ch01-01-installation.html
https://blog.mzumi.com/post/2016/10/18/hello-ffi/