とりあえずは、Hello World的なものを作ってみます。
こんだけ。
これをブラウザ上で表示出来るようにしてみます。
起動用のhtmlになります。
"nimtest04.js"ですが、こちらはこの後コンパイルした際に、WebAssembly(.wasm)ファイルと一緒に出力される起動用のJavaScriptです。
EmscriptenでWebAssemblyの関数を呼び出す方法は2通りあるようです。
一つは、"ccall"を用いてWebAssemblyの関数にダイレクトにアクセスする方法
もう一つは、"cwrap"を用いて、変数をWebAssemblyの関数にバインドしてから、通常の関数の様に呼び出す方法です。
今回は両方試してみる事にします。
VisualStudio Code でコンパイルするので、"tasks.json", "launch.json"も作成します。
あと今回は、C言語のコンパイラが違ったり、今までの設定だと上手く動かないので、nimのコンパイル設定を変更する必要があります。
nimのインストール先にある設定ファイルを変更しなくても、今回の作業フォルダに、"nim.cfg"を作成しておけば記載された内容に部分だけ設定が上書きされるので作成します。
嵌ったのは、3,4行目
他のWebサイトの解説の多くは clang.exe = "emcc" とかなっていますが、Windows環境だとエラーになります。
理由は、"emcc.bat" があるフォルダに拡張子なしの "emcc" もあるからです。
(unix環境でコンパイルするためのスクリプトのような気もするので削除すれば動くような気もしますが試してはいません)
これでコンパイルが通ったら、nimtest04.wasm と、nimtest04.js が出来ているはずです。
ここまでで、JavaScriptからWebAssemblyコードの呼出し方は分かりましたが、逆に WebAseembly側からJavaSriptのコードを呼出したりDOMの操作を行ったりする方法について検証します。
WebAsmからJavaScriptのコードを呼び出すには、emscripten_run_script という命令 ( 値を返す場合は、emscripten_run_script_string や emscripten_run_script_int ) を使用するという事なので、次のようなコードを作成してみました。
これを実行するとRuntimeError: memory access out of bounds
のエラーが吐かれます。
ネットで調べると、Emscriptenのコンパイルオプションに、"ALLOW_TABLE_GROWTH=1","ALLOW_MEMORY_GROWTH=1" を付けると良いみたいな事が書かれているのですが、効果なし。
そもそもこんなチンケなプログラミングでメモリが足りないっておかしいだろ。
2020/12/10追記 何か原因がわかりましたので、こちらに記事を追加しています
1週間ぐらい悩んだ挙句、C言語で言うところのmain()の処理部分(nimだと関数外のコードですね)に同じようなコードを記述した場合、いい感じに動作する。
それと main()の処理が、onRuntimeInitializedの後に動作している事に気づいた。
そこで、こんな感じにコードを変更してみました。
初期化処理の完了を onRuntimeInitialized で判断するのではなく、main()関数実行時にJavaScriptの関数を呼び出すように変更してみました。
実行結果はこんな感じです。
何とか想定通りの出力が行われました。
WebAssmbly側からJQueryの呼出しも問題ないようですね。
正直これでいいのかわからないし、実際別の正しいやり方があるのだとは思うのですが、ネット調べても見つからないし、仕方ないので今回はこれで良しとします。