2013-07-26 2 views
26

私はEmscripten/javascriptだけでなく、このOverstackコミュニティも初めてです。私の状況がすでに解決されていれば、事前にお詫び申し上げます。コンパイルされたコードをemscriptenに渡す/返す配列ポインタを処理する方法は?

Windows 7の環境では、emccを使って単純なCプログラムをコンパイルしました。これは、配列を受け入れ、変更します(下記参照)。

emccの-oオプションを使用して、ブラウザにロードした.htmlファイル(Chrome)を生成しました。

python emcc displayArray7.c -o displayArray7.html -s EXPORTED_FUNCTIONS="['_main', '_displayArray' 
ロード時に、ブラウザウィンドウ内で生成される出力が期待どおりであることがわかります(下記参照)。

JavaScriptコンソールを介しmodule.cwrap()コマンドを使用して、直接機能を起動しようしかし
doubleVector[0] = 1.000000 
doubleVector[1] = 2.000000 
doubleVector[2] = 3.000000 
modified doubleVector[0] = 98.000000 
modified doubleVector[1] = 99.000000 
modified doubleVector[2] = 100.000000 
array1[0] = 98.000000 
array1[1] = 99.000000 
array1[2] = 100.000000 
array2[0] = 98.000000 
array2[1] = 99.000000 
array2[2] = 100.000000 

、((メインの外))、

> displayArray=Module.cwrap('displayArray', '[number]', ['[number]']) 

> result = displayArray([1.0,2.0,3.0]) 
[1, 2, 3] 
> result 
[1, 2, 3] 

Iが生成され、次のを見ています/私が見たいものではないブラウザに表示されます。私は、次の質問を持っている

doubleVector[0] = 0.000000 
doubleVector[1] = 0.000000 
doubleVector[2] = 0.000000 
modified doubleVector[0] = 100.000000 
modified doubleVector[1] = 100.000000 
modified doubleVector[2] = 100.000000 

は:

  1. 私はModule.cwrapに私の呼び出しで正しいをリスト戻り値の型およびパラメータ()の正しい構文を持っていますか?私はint_sqrt()ルーチンにポインタ以外の変数を渡すことを扱うチュートリアルの "コードとのやりとり"のセクションで、int_sqrt()のシンプルで簡単な例をうまく実行しました。

  2. emscriptenで生成されたjavascriptコードに配列やポインタが渡された(または返された)ときに、何か違うことがありますか?

  3. displayArray()関数のブラウザで生成された出力は、main()から呼び出されたときに期待どおりに動作します。しかし、javascriptコンソール経由ではありませんか?

私はEmscripten/javascriptを新規に使用しています。情報/サポートは非​​常に高く評価されます。

はありがとう、

FC

答えて

32

Module.cwrapの期待される形式は、「配列の関数に渡すことを可能にしていますが、配列を返すようにしようとすると、結果に主張すると失敗します

displayArrayA=Module.cwrap('displayArray','array',['array']) 
displayArrayA([1,2,3]) 
// Assertion failed: ccallFunc, fromC assert(type != 'array') 

本の第二の制限は、あなたが符号なしの8ビット数値にすべての着信ダブル配列を変換する必要があるだろうという意味、入ってくる配列はバイト配列であることが予想されるということである

displayArrayA=Module.cwrap('displayArray','number',['array']) 
displayArrayA(new Uint8Array(new Float64Array([1,2,3]).buffer)) 

このようにメソッドを呼び出すと、呼び出された関数の実行後にリセットされるEmscriptenスタックに配列が一時的にコピーされ、返された配列オフセットは解放されるたびに使用できなくなる可能性があります。

Emscript Heapシステム内で配列の割り当てと保存を行うことが、関数の結果を望むなら、はるかに望ましいことです。

Emscriptenコードは、Emscriptenのヒープ領域内に割り当てられたメモリにのみアクセスできます。関数に渡そうとしている配列が、Emscriptenコードが実行されているヒープの外側に割り当てられていて、入力引数で予想される未処理のポインタ型と一致しません。

データを関数に渡すために配列にアクセスできる方法はいくつかあります。これらのすべてはEmscripenがemscripten Module.HEAP *の中にあなたのメモリの場所を知っていることを必要とするので、最初のステップでEmscripten "_malloc"関数を呼び出すことがあります。

var offset = Module._malloc(24) 

これは、あなたの3倍の8バイトのダブル配列のために必要なEmscriptenヒープに必要な24のバイトを割り当てることができ、およびU8 TypedArrayを示すEmscriptenヒープのオフセット番号は、あなたの配列の予約をオフセットを返します。このオフセットはポインタであり、生ポインタのオフセットを使用するように設定されている場合、自動的にcwrap displayArray関数に渡されます。

  1. は、メモリを設定します。あなたがアクセスしたり、配列の内容を変更したい場合は、この時点で

    displayArray=Module.cwrap('displayArray','number',['number']) 
    

    、限り、malloc関数が有効であるとして、あなたは、少なくとも以下のオプションがあります

  2. アクセス

    次の2つの方法を除いて値を回復する簡単な方法で、
    Module.HEAPF64.set(new Float64Array([1,2,3]), offset/8); 
    displayArray(offset); 
    
  3. を一時的に包まれたのfloat64配列を使用してModule.setValueはオートマチックには「double」のヒントを使用します。 LYあなたはJavascriptの側でより広範囲にポインタを使用したい場合は、手動HEAPF64エントリオフサブアレイTypedArrayを引くことができます8.

    Module.setValue(offset, 1, 'double') 
    Module.setValue(offset+8, 2, 'double') 
    Module.setValue(offset+16, 3, 'double') 
    displayArray(offset) 
    var result = []; 
    result[0] = Module.getValue(offset,'double'); //98 
    result[1] = Module.getValue(offset+8,'double') //99 
    result[2] = Module.getValue(offset+16,'double') //100 
    
  4. で割った、オフセットHEAPF64を変更します。これにより、関数の実行が終了した時点で値を簡単に読み取ることができます。このTypedArrayはEmscriptenの他の部分と同じヒープに裏打ちされているので、Javascriptの側で実行されたすべての変更がEmscripten側とその逆に反映されます。

    var doublePtr = Module.HEAPF64.subarray(offset/8, offset/8 + 3); 
    doublePtr[0] = 1; 
    doublePtr[1] = 2; 
    doublePtr[2] = 3; 
    // Although we have access directly to the HEAPF64 of the pointer, 
    // we still refer to it by the pointer's byte offset when calling the function 
    displayArray(offset); 
    //doublePtr[] now contains the 98,99,100 values 
    
+2

非常に役に立っ答えを。時間を節約して髪を引っ張ってくれます。ありがとうございました。 – scai

+0

本当に助けになりましたが、「他の方法」はどうですか?どのようにあなたはCコードから配列を変更し、Javascriptで使用できますか? – gromit190

+0

'Module.malloc()'は見えますが、 'Module.free()'はありません。それはJSのGCによって処理されますか? – Nikkolasg

関連する問題