WebGL-Native: WASM内関数ポインタのコールバックに対応する
prev: https://zenn.dev/okuoku/scraps/80221b8286b8d9
next: https://zenn.dev/okuoku/scraps/06bf07df1a36a9
久々にがっつり間違えてしまった。。仕切り直し。
関数ポインタに対応する
WebAssemblyでは個々のオブジェクト(関数や変数)が載った統合的な構造体である table
と export
および import
が独立して存在する。で、前回までの対応では export
または import
された関数しか呼ばれないという仮定を置いていたが、それが 間違い だったので実装をやりなおす必要がある。。
幸い、 wasm2c
では、tableへのデータ投入もがんばればパースできる形で変換しているため、それをがんばってCMakeでパースすることにする。
パースしたい要素は、
func_types[136] = wasm_rt_register_func_type(9, 1, WASM_RT_I32, WASM_RT_I32,
WASM_RT_I32, WASM_RT_F32, WASM_RT_I32, WASM_RT_I32, WASM_RT_I32,
WASM_RT_I32, WASM_RT_I32, WASM_RT_I32);
のような行で、これを、数十MiBのCソースコードから見つけて WASM_RT_[I|F][32|64]
のリストを得たい。従来は export/import される関数のみをターゲットとしていたので wasm2c
が生成する .h
にある関数プロトタイプ宣言をパースしていたが、それだと不十分なことが明かになった。
... というのも、どうもEmscriptenのランタイムはexportしていない関数をDOMイベントのコールバックとしてJavaScript側に渡しているようで、これをJavaScriptから呼ぶ際にも他のexportと同様にNCCCの呼出しプロトコル変換が必要になってしまう。
動いた
... が超クッソ激烈に遅い。。
2.4fpsて
Unityで使っている古いEmscriptenに対応したらN-API化すべきかな。。ボトルネックとして思いつくのが、関数の引数の設定や参照に毎回Pointerオブジェクトを作っていることなので、そこを省略するには ffi-napi
に相当するコードを自分で用意するしかない。