2017-10-14 8 views
2

wasm w/emccにコンパイルし、Webブラウザで実行するための小さなCプログラムを作成しています。 wasmエクスポートされた関数はパラメータの入力と戻り値として単純な数値のみを受け入れることができるので、文字列やchar配列などのより複雑なデータ型にアクセスするにはJavaScript APIとコンパイル済みWebAssemblyコードの間でメモリを共有する必要があります。問題は、私の人生のために私のCプログラムの内部からWebAssembly linear memoryにアクセスする方法を理解できないということです。C/C++からWebAssemblyリニアメモリにアクセスする方法

究極の目標は、私のCプログラムの中でJavaScriptで初期化された文字列を読み込み、さらにC言語のプログラムで修正または初期化された文字列をWebブラウザのJavaScriptコードで読み込むことです。ここで

は、私が何をしようとしているの基本的な例です。

main.js

const importObject = { 
    'env': { 
    'memoryBase': 0, 
    'tableBase': 0, 
    'memory': new WebAssembly.Memory({initial: 256}), 
    'table': new WebAssembly.Table({initial: 0, element: 'anyfunc'}) 
    } 
} 

// using the fetchAndInstantiate util function from 
// https://github.com/mdn/webassembly-examples/blob/master/wasm-utils.js 
fetchAndInstantiate('example.wasm', importObject).then(instance => { 

     // call the compiled webassembly main function 
     instance.exports._main() 
     console.log(importObject.env.memory) 
}) 

はexample.c

int main() { 
    // somehow access importObject.env.memory 
    // so that I can write a string to it 
    return 0; 
} 

This questionは私の道の一部を取得しますしかし、私はまだ私のCコードでWebAssemblyメモリバッファから読み書きする方法を理解していません。

答えて

1

実行する必要があることは、WebAssemblyモジュール内で、CコードとJavaScriptコードの両方に読み書きする場所を通信することです。

ここでは、配列の各要素に数値を追加する単純な例を示します。

const int SIZE = 10; 
int data[SIZE]; 

void add(int value) { 
    for (int i=0; i<SIZE; i++) { 
    data[i] = data[i] + value; 
    } 
} 

int* getData() { 
    return &data[0]; 
} 

上記のコードで重要なことはdata配列の先頭への参照を返すint* getData()関数である:これは、Cコードです。 WebAssemblyにコンパイルすると、モジュールの線形メモリ内のdata配列の位置である整数が返されます。

は、ここでそれを使用する方法の例です:

var wasmModule = new WebAssembly.Module(wasmCode); 
var wasmInstance = new WebAssembly.Instance(wasmModule, wasmImports); 

// obtain the offset to the array 
var offset = wasmInstance.exports.getData(); 

// create a view on the memory that points to this array 
var linearMemory = new Uint32Array(wasmInstance.exports.memory.buffer, offset, 10); 

// populate with some data 
for (var i = 0; i < linearMemory.length; i++) { 
    linearMemory[i] = i; 
} 

// mutate the array within the WebAssembly module 
wasmInstance.exports.add(10); 

// log the results 
for (var i = 0; i < linearMemory.length; i++) { 
    log(linearMemory[i]); 
} 

あなたはこのWASM fiddleに完全な例を見ることができます。

0

2つの反対のアプローチがあります。

  1. はグローバルとしてすべてのデータ要素を宣言し、それぞれのアドレスを初め返すためにヘルパー関数を追加します。
  2. グローバルを使用せず、JSで目的のメモリを割り当て、オフセットを計算し、呼び出された関数にそれらのオフセットを渡します。この場合、使用可能なメモリは0(ゼロ)から開始します。

(1)は単純なものでOKです。 (2)は、データサイズが不明な場合に適しています。

関連する問題