ClangでWebAssemblyにコンパイル
前回までに必要なツールは揃ったので、コンパイル + 出力コードの検証を進めていきます。
コンパイル方法
以下のコードをコンパイルすることを想定します。
これを WASM にコンパイルするには以下のコマンドで OK です。
clang がコンパイル、wasm-ld がリンクです。今回はエントリポイントがないため、wasm-ld に --no-entry を渡しています。
出力されたコードをテキストフォーマットにして中身を見てみます。
足し算をする「add」関数が出力されているのがわかります。
ところで、出力されたコードをみると「__heap_base」という変数が定義されていました。動的にメモリを確保する場合は、なんとなく、ここをベースにヒープ領域の確保していくのが良さそうです。
外部公開とエントリポイント
C の関数を JavaScript 側から呼べるようにするには、関数の前に
__attribute__((used))をつけます。検索すると
__attribute__((visibility("default")))と書くとあったのですが、なぜかこちらではうまくいきませんでした。
公開した関数は、JavaScript 側から同じ名前で呼び出せます。
先程は、wasm-ld に --no-entry をつけてリンクしましたが、エントリポイントを設定する場合は不要です。エントリポイントは _start という名前の関数になります。シグネチャは何でも良さそうです。
ところで、この _start が、いつ呼ばれているのか?戻り値はどうやって取得しているのか?そもそも自動的に呼ばれているのか?などはよくわかりません。今度調べてみます。
C 関数から文字列を受け取る
C 関数から char 型のポインタを返すと、当然そのポインタアドレスが返ります。そこで、そのアドレスからバッファを読んでデコードすれば JavaScript の string オブジェクトに変換できます。
もうちょっと効率のいい方法があるきがしますが、まぁ、いいか。
まとめ
WASM へのコンパイル方法と、関数の公開方法を紹介しました。次回は、C 側から JavaScript の関数を呼ぶ方法を実験してまとめたいと思います。