Open2

WebGL-Native: WASM内関数ポインタのコールバックに対応する

okuokuokuoku

prev: https://zenn.dev/okuoku/scraps/80221b8286b8d9
next: https://zenn.dev/okuoku/scraps/06bf07df1a36a9

久々にがっつり間違えてしまった。。仕切り直し。

関数ポインタに対応する

WebAssemblyでは個々のオブジェクト(関数や変数)が載った統合的な構造体である tableexport および 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の呼出しプロトコル変換が必要になってしまう。

okuokuokuoku

動いた

https://github.com/okuoku/cwgl-proto/commit/e3bab0172298408e4e2ddebc7855282c9da5b3ab

... が超クッソ激烈に遅い。。

2.4fpsて

Unityで使っている古いEmscriptenに対応したらN-API化すべきかな。。ボトルネックとして思いつくのが、関数の引数の設定や参照に毎回Pointerオブジェクトを作っていることなので、そこを省略するには ffi-napi に相当するコードを自分で用意するしかない。