2014年5月11日日曜日

Emscripten, C++, JavaScripte: EM_ASM_ARGS と文字列の渡し方

C++コードからEM_ASMでJavaScriptネイティブアセンブリーコードを呼びたい事がままあったりします。この時、EM_ASM_ARGSを使うと引数をC++コードからJavaScriptへ渡せますが、文字列を渡す為には少しだけ内部実装を知らないとなりません。


成功するとこうなるの図。

先ず、やりがちな上手く文字列として扱えていない例。

code: 文字列を文字列として扱えていない例( result_web.txt に注目 )

単純に整数値を渡すのと同じように文字列を渡せると思っていると、このように謎の整数値が渡っていて、残念、文字列は渡せないのかと思ってしまうやもしれません。

渡せます。文字列渡せます。というか、既に渡ってます(╹◡╹)

code: 文字列を文字列として扱う例( result_web.txt で文字列が出てる )

今回は渡した文字列を文字列として扱えています。Emscriptenでは文字列を整数値の配列として扱います。EM_ASM_ARGSの呼び出しではEmscriptenの仕組みとしてのスタックに文字列の為に確保された配列の先頭アドレス、つまりEmscriptenの仕組みとしての文字列先頭要素へのポインターが渡ります。これをEmscriptenの仕組みとしてのポインター値からJavaScripteネイティブ文字列に変換するには Pointer_stringify 関数を使う必要があるのでした。

参考:

  1. https://github.com/kripken/emscripten/wiki/Interacting-with-code#other-methods
Strings in JavaScript must be converted to pointers for compiled code, the relevant functions are Pointer_stringify which given a pointer returns a JavaScript string, and the other direction can be accomplished by allocate(intArrayFromString(someString), 'i8', ALLOC_STACK) which will convert a JavaScript string someString to a pointer. Note that conversion to a pointer allocates memory (that's the call to allocate there), and in this case we allocate it on the stack (if you are called from a compiled function, it will rewind the stack for you; otherwise, you should do Runtime.stackSave() before andRuntime.stackRestore(..that value..) afterwards).

0 件のコメント:

コメントを投稿