ついにChromeとFirefoxにWebAssembly(WASM)がやってきました!まだWASMに対応していない他のブラウザも、じきに実装するはずです。

WASMを利用することで、C/C++やRustなどのプログラミング言語を用いて、ブラウザ上で動作するプログラムを組むことができます。まずはRustを使って簡単なWASMの利用方法について学んでみましょう。

RustのWebAssembly開発環境を整える

Rustのインストール

すでにRustがインストールされている場合はこの手順を飛ばしてもらっても構いません。

まずはrustupをインストールします。rustupはRust開発環境のインストールを補助するツールです。

次にrustupでRustをインストールします。

rustcのバージョンをチェックして、WebAssemblyをサポートしている1.14以降であることを確認しましょう。

ターゲットにWebAssemblyを追加する

RustのインストールができたらWebAssemblyをターゲットに追加します。

これでRust側の準備は完了です。

Emscriptenのインストール

RustのコードからWebAssemblyを生成するにはEmscriptenというものを使います。

Emscriptenはhomebrewにも存在しますが、そのままだと動かないので、以下の手順で手動でダウンロードすることをお勧めします。

まずはEmscripten SDKをインストールします。以下のリンクからダウンロードしてください。ここではPortable版を例に進めていきます。

http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#download-and-install

ダウンロードが完了したら解凍して、出てきたフォルダに移動しましょう。

また、cmakeが必要になるので、まだ入っていない場合はhomebrewなどで入れておいてください。

そして次のコマンドを実行してEmscriptenをインストールします。Emscriptenのバージョンは1.37以降が必要になるので、現在のところ、latestではなく、incomingをインストールします。

installには非常に長い時間がかかるので注意してください。

installとactivateが終わったら環境変数を設定します。

これでEmscriptenの準備は完了です。

ブラウザの準備

現在WebAssemblyに対応しているブラウザはChrome57以降か、Firefox52以降です。対応するブラウザをインストールしておきましょう。

Hello, WebAssembly!

これで準備ができました。それではさっそくRustからWebAssemblyに変換してみましょう!適当な作業ディレクトリを作って、その中にhello.rsというファイル名で簡単なRustコードを書きます。

これをWebAssemblyにコンパイルします。

これで必要なファイル一式が出力されます。HTTPサーバを立ててアクセスしてみましょう。

「http://localhost:8000/hello.html」でアクセスできます。

おめでとうございます!「Hello, WebAssembly!」が表示されました!

JavaScirptからwasmファイルを読み込んで実行する

「Hello, WebAssembly!」の例ではEmscriptenにhtmlファイルも生成してもらっていました。しかし実際には自前のHTMLファイルを使用するのが一般的です。今度は自分で読み込み処理を書いてみましょう。

事前のhtmlファイルからwasmファイルを実行するには、Emscriptenが生成するjsファイルを利用します。htmlファイルを自動生成せずに、このjsファイルのみを生成するには、コンパイル時の出力拡張子を.jsにします。

このコマンドを実行するとhello.wasmとhello.jsファイルが生成されます。

次にhello.htmlファイルを自分で作成します。そして次のように書きます:

EmscriptenではグローバルなModuleオブジェクトというものを利用してwasmの管理を行います。まず、空のModuleオブジェクトを作成し、wasmファイルの内容を読み込み、Module.wasmBinaryにwasmファイルの内容を入れます。あとは先ほど生成したhello.jsをscriptタグで追加し、実行するだけです。

これで準備ができました。サーバを立て、このhtmlファイルを開いてみましょう。

「http://localhost:8000/hello.html」でアクセスできるはずです。アクセスできたら、コンソールを開いて、結果を確認してみましょう。

「Hello, WebAssembly!」と表示されているはずです。

Rust(wasm)側の関数をJavaScriptから呼び出す

次はRust(wasm)側の関数をJavaScriptから呼び出してみましょう。次のようなRustコードがあるとします:

関数sumはその名の通りふたつの引数の合計を返す関数です。これをJavaScriptから呼び出してみましょう。

このとき関数に#[no_mangle]をつけることを忘れないでください。#[no_mangle]はマングリングを防ぐためのものです。マングリングというのは、簡単に言うと、コンパイル時にコンパイラの都合のいいように名前を勝手に変更する機能です。#[no_mangle]を指定することで、関数「sum」には余計なことをせず確実に「_sum」として出力されるようになります。

これをコンパイルします。

コンパイル時にEXPORTED_FUNCTIONSとして、JavaScript側に露出する関数の名前を列挙します。関数名の前にアンダースコアがつくことに注意してください。

また、関数が増えてくるとコンパイルのコマンドが冗長になるので、cargoを利用して、-C link-argsはcargo.tomlに書くといいかもしれません。

次にメインとなるjsファイルを用意します。これをmain.jsとしましょう。main.jsからRustの関数を呼び出すには次のようにします:

Rust側の関数を呼び出すには、EmscriptenのModuleオブジェクトが持っているcwrapメソッドを使用します。crawpメソッドは、関数名、戻り値型、引数型の3つを引数に取ります。指定できるのはnumber、string、arrayの3つです。

次にhtmlファイルを編集して、main.jsを読み込むようにします。

これで完成です。サーバを起動してアクセスしてみましょう。

Rust側の関数が、ちゃんと実行されました!