さっき決めたブログ

[Nim]NimでWebAssemblyを作成する

2020年7月26日 12:33 PM01.42KNimPROGRAMNimWebAssemblyEmscripten

とりあえず書いてみる

とりあえずは、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 が出来ているはずです。

出ました😁
実行結果

DOMをいじったり、JavaScriptの関数呼んだり

ここまでで、JavaScriptからWebAssemblyコードの呼出し方は分かりましたが、逆に WebAseembly側からJavaSriptのコードを呼出したりDOMの操作を行ったりする方法について検証します。

WebAsmからJavaScriptのコードを呼び出すには、emscripten_run_script という命令 ( 値を返す場合は、emscripten_run_script_stringemscripten_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の呼出しも問題ないようですね。
正直これでいいのかわからないし、実際別の正しいやり方があるのだとは思うのですが、ネット調べても見つからないし、仕方ないので今回はこれで良しとします。

感想

  • まだ良く分かっていない部分多し
  • 開発環境の構築がクソめんどい(特にWindows環境)
  • 現時点ではまだWebAssembly単体では動作することは出来なく、JavaScriptが必要みたい
  • 頑張れば大概のことは出来そう、でもJavaScriptで事足りるから現時点では使用は局所的になるのかな?
  • ローカル環境での起動ができない。
    試していないが、FireFoxなら出来るみたい。他のブラウザでもWindows自体のmime-typeを設定すればいけるのかな?
  • 速さとかはよくわからない

ここまでのコード

nimtest04.zip

参考にしたサイト

nimでWeb Assemblyをやってみる
https://qiita.com/musou1500/items/84f5a238cfb1ef1f92bf
Windows上でのEmscriptenのセットアップ
https://qiita.com/takao_mofumofu/items/c331d0e4345eb0f353ae
Emscripten
https://emscripten.org/
python
https://www.python.org/
NimとCでもWebAssemblyやってみた
https://qiita.com/snowlt23/items/5f05da45cbd1df4abb07
New web-like targets (WebAssembly, etc.) #8738
https://github.com/nim-lang/Nim/pull/8738
WebAssemblyの使用方法と初期化、エラーハンドリング
https://medium.com/axip/webassembly%E3%81%AE%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E3%81%A8%E5%88%9D%E6%9C%9F%E5%8C%96-%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0-5b0a8c3968df
他ありすぎて忘れた。。。

投稿者プロフィール

KARASU
うーん いろいろ考え中。。。

コメント

コメント取得中...

関連記事

TOPへ