【Emscripten】 C++ でJSの関数を関数ポインタとして使う
TOC
ものすごく久しぶりの投稿となってしまいました。すみません。
今回は、Emscripten で C++ を実行するときに、
JSの関数を関数ポインタとして登録し、それを呼び出せるようにする方法を紹介します。
実行環境
- Ubuntu 14.04.5 LTS
- emcc 1.36.0
- clang version 3.9.0
やりたいこと
- JS の関数を
set_js_listener
関数を使用して登録する call_listener
関数を呼び出した時、登録した JS の関数を実行する
手順1: set_js_listener、call_listener 関数を実装
1 | typedef void(*JS_LISTENER)(); |
typedef を利用して、型を簡略化して使用できるようにしています。
また、set_js_listener
は、EMSCRIPTEN_BINDINGS
は使用せず、
ビルド時に EXPORTED_FUNCTIONS
で js から呼び出せるようにします。
そうしないと、次のようなエラーが出ます。
(EMSCRIPTEN_BINDINGS、allow_raw_pointers を使用した場合)
手順2: ビルドする
1 | $ emcc main.cpp -std=c++11 -s RESERVED_FUNCTION_POINTERS=1 --bind -s EXPORTED_FUNCTIONS="['_set_js_listener']" |
それぞれの引数は、次のような意味があります。
std=c++11
を指定しないと、embind を使用する際にエラーが出ます。-s RESERVED_FUNCTION_POINTERS=1
: 1つの関数ポインタを使えるようにします。--bind
: embind を使えるようにします。-s EXPORTED_FUNCTIONS="['_set_js_listener']"
: set_js_listener を js から呼び出せるようにします。
手順3: 関数ポインタをJSで作成する
1 | var fnPointer = Runtime.addFunction(function() { |
関数ポインタは、Runtime.addFunction
を通して使用します。
set_js_listener は、Module.ccall
を使用して呼び出します。
手順4: 登録した関数ポインタを呼び出す
JS から関数ポインタを呼び出します。1
Module.call_listener();
called!
とコンソールに出力されたので、登録した関数が呼び出されたことがわかります。
コード
今回実行したコードは次のようになりました。
参考
http://stackoverflow.com/questions/12358877/passing-js-function-to-emscripten-generated-code