ClangでWebAssemblyにコンパイル


前回までに必要なツールは揃ったので、コンパイル + 出力コードの検証を進めていきます。

コンパイル方法

以下のコードをコンパイルすることを想定します。

コード1: test.c

これを WASM にコンパイルするには以下のコマンドで OK です。

clang がコンパイル、wasm-ld がリンクです。今回はエントリポイントがないため、wasm-ld に --no-entry を渡しています。

出力されたコードをテキストフォーマットにして中身を見てみます。

コード2: テキストフォーマットへの変換
コード3: test.wat

足し算をする「add」関数が出力されているのがわかります。

ところで、出力されたコードをみると「__heap_base」という変数が定義されていました。動的にメモリを確保する場合は、なんとなく、ここをベースにヒープ領域の確保していくのが良さそうです。

外部公開とエントリポイント

C の関数を JavaScript 側から呼べるようにするには、関数の前に

__attribute__((used))
をつけます。検索すると
__attribute__((visibility("default")))
と書くとあったのですが、なぜかこちらではうまくいきませんでした。

公開した関数は、JavaScript 側から同じ名前で呼び出せます。

先程は、wasm-ld に --no-entry をつけてリンクしましたが、エントリポイントを設定する場合は不要です。エントリポイントは _start という名前の関数になります。シグネチャは何でも良さそうです。

ところで、この _start が、いつ呼ばれているのか?戻り値はどうやって取得しているのか?そもそも自動的に呼ばれているのか?などはよくわかりません。今度調べてみます。

C 関数から文字列を受け取る

C 関数から char 型のポインタを返すと、当然そのポインタアドレスが返ります。そこで、そのアドレスからバッファを読んでデコードすれば JavaScript の string オブジェクトに変換できます。

コード4: C のコード
コード5: JS のコード

もうちょっと効率のいい方法があるきがしますが、まぁ、いいか。

まとめ

WASM へのコンパイル方法と、関数の公開方法を紹介しました。次回は、C 側から JavaScript の関数を呼ぶ方法を実験してまとめたいと思います。