WebAseembly+Emscripten で別ファイルで定義されているモジュールの動的リンクについて検証しました。
Emscriptenを用いた環境でのモジュールの動的リンクは、dlopen, dlsym といった命令を使用するようです(Linux等と同じらしい)。
ただし読込まれるモジュールは、Emscriptenの仮想ファイルシステム上に存在するもの限られ、 Web上にあるモジュールを直接ロードする事は出来ないようです。
Webからモジュールファイルをダウンロードして、仮想ファイルに書込み後 dlopen するというやり方も考えられますが、ひとまず --preload-file オプションでサブモジュールの実行ファイルがあらかじめ仮想ファイルシステム上に存在している前提で進めます。
最初に普通に作成した場合の動作を検証します。 先に述べておくと、こちらのケースは上手く動きませんが、出力されるエラーの内容が次に行う検証に繋がったので、載せておきます。
まずは検証用のサブモジュールを2つ作成します。
どちらにもエントリポイントとして subModule プロシージャを定義しておきます。 この2つのモジュールをメインモジュール側で切り替えて、subModule を呼び出しそれぞれ違う結果が出力される事を検証していきます。
メインモジュールはこんな感じで作成しました。
サブモジュールは、noMain = "on" と SIDE_MODULE=1 を付けてコンパイルしています。 メインモジュールの方は、MAIN_MODULE=1 をつけているのと、--preload-file ./preload@/ で事前にコンパイルしてあるサブモジュールの実行形式を仮想ファイル化しています。
起動用のhtmlは特段変わったところはなく、今までと同じです
冒頭でも述べた通り、今回の検証は dlopen の実行に失敗しエラーとなります。
Chromeのコンソールを見てみると dlerror がこのようなメッセージを出力しているのが見れます。
RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.
どうも、バッファサイズが4Kより大きい場合はメインスレッドでのコンパイルが出来ないとのことなので、サイズを小さくするかワーカスレッド上でコンパイルするようにとの事です。
これ以上サイズを小さくするのは難しそうなので、次にWebWorkerを用いてワーカスレッド上で動作させる検証を行います。