2014年5月11日日曜日

Emscripten, C++, JavaScript: EM_ASM_ARGS を使わない事実上の引数を渡したようなJSコードの実行とJS側から文字列をC++に返す簡単な方法とPCではfilesystem、WebではlocalStorageを使うsave/loadのexample。

1つ前の記事EM_ASM_ARGS を使いJS側で実行したいコードにC++側から文字列の引数を渡す方法を書きました。

今回はEmscriptenの仕組み(スタック、ポインター、文字列の表現など)をすっ飛ばしてC++側から手っ取り早く任意の文字列を任意のJSアセンブリーコードとして実行させたり、逆にJS側からC++へ文字列を返す方法について。

EM_ASM_ARGS に代えて emscripten_run_script を使います。 EM_ASM_ARG ではFFI的な関数呼び出し風の体裁を保っていましたが、 emscripten_run_script を使う場合はまさにそのままコードを文字列として生成して評価させます。つまり、いわゆる eval() です。
EM_ASM_ARGS( { console.log( $0 ); }, 12345 );
と、
emscripten_run_script( std::string( "console.log( '" ) + std::to_string( 12345 ) + "');" );
が等価です。

EM_ASM 系でも文字列を渡してJSアセンブリーコード側で Pointer_stringify によりJavaScript文字列を得られる点は前述の1つ前の記事で書きました。しかし、 EM_ASM 系の機能群にはJS側から結果として文字列のreturnを得る方法は直接的には用意されていません。

その点、 emscripten_run_script 系の機能群には、emscripten-1.16.0現在で、
  • extern void emscripten_run_script( const char* script);
  • extern int emscripten_run_script_int( const char* script);
  • extern char* emscripten_run_script_string( const char* script);
以上の3種類が用意されています。(詳しくは system/include/emscripten/emscripten.h  を読むと丁寧なコメント付きで分かります。)

emscripten_run_script_string を使うと、評価する仮引数scriptに与えるJSアセンブリーコードの結果文字列としてC++コード側で簡単に取得できます。

この機能を使った、PC版ではfstreamによりファイルシステムを、Web版(Emscripten版)ではWeb Storageの Local Storage により擬似的にファイルシステムっぽい何かを扱ってデータを save/load する簡単な example は以下のようになります。




Web版では localStorage 、PC版では fstream で load/save を使うアプリ側からは最低限同じようにあるパスをキーにデータをR/Wできています(╹◡╹)

このシンプルな example に、存在しないディレクトリーへの配慮や、提供したいプラットフォームのファイルシステムで対応不能なパス文字列への対処、文字列以外のデータへの対応(BASE64エンコード/デコードを盛り込むとか)などを施すとそこそこ実用的なPC/Web共用のR/W対応で永続的なストレージを扱うコード実装になります。

なるはずです。なる予定です。

0 件のコメント:

コメントを投稿