EmscriptenでJSとCで相互にデータをやり取りする
Emscripten で JavaScript の世界と C の世界でデータをやり取りする方法をメモ (with ccall/cwrap)。
C や C++ 側で必要なこと
Emscripten でコンパイルすると、main
から到達できないコードは dead code elimination でサクサク消されちゃうので
関数に EMSCRIPTEN_KEEPALIVE
を付けて消されないようにしておく必要がある
(EMSCRIPTEN_KEEPALIVE
自体は __attribute__((used))
に展開されるっぽい。環境によるとは思うけど)。
コンパイルは
emcc -s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS="['ccall']" -o index.html main.cc
とかで。NO_EXIT_RUNTIME
にしておくことで、 main
を実行したあとランタイムを止めるというデフォルトの挙動を変更できる。
ExPORTED_RUNTIME_METHODS
に cwrap
とかを入れておくと cwrap から使えるようになる。
ccall や cwrap で関数を呼び出すときの基本的な方法
Module.cwrap('hoge', 'string', 'number')(5);
WebAssemblyを触ってみた
めっちゃお久しぶりです。
WebAssembly でハロワ的なサムシングを C++ でやったらすんなり動きすぎて感動したというポストです。
動機としては C++ で書いた SMF (Standard MIDI File) のパーサをブラウザ上で使いたかった
ということです。別に速度を求めていたとかそういうわけではないのですが、バイナリを扱うのはやっぱり
JavaScript よりも C++ とかの方がぱぱっと書けるかな、という。
で、使ったコードはリンク先に置いてあります。
https://github.com/kofuk/haystack/blob/df5d58caadf1ca640fef80484ac138faa6090c14/smf.cc
一応ビッグエンディアンをリトルエンディアンに変換している部分が wasm での挙動が予想できないため
不安な要素だったんですが、リトルエンディアンと考えていいみたいでした。
(これってコンパイルされた wasm をビッグエンディアンのマシンに持っていったら動かないみたいなことはあるんだろうか)。