emcc
でwasmにコンパイルしてWebブラウザで実行することを目的とした小さなCプログラムを書いています。 wasmでエクスポートされた関数は、パラメーター入力と戻り値として単純な数値のみを受け入れることができるため、文字列やchar
配列などのより複雑なデータ型にアクセスするには、JavaScriptAPIとコンパイルされたWebAssemblyコードの間でメモリを共有する必要があります。問題は、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;
}
この質問 途中で私を取得しますが、CコードのWebAssemblyメモリバッファからの読み取り/書き込み方法がまだわかりません。
あなたがする必要があるのは、CコードとJavaScriptコードの両方が読み書きするWebAssemblyモジュール内の場所を通信することです。
これは、配列の各要素に数値を追加する簡単な例です。これはCコードです:
_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];
}
_
上記のコードで重要なのは、int* getData()
関数です。これは、data
配列の先頭への参照を返します。 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 で完全な例を見ることができます。
2つの反対のアプローチがあります:
(1)簡単なことでも大丈夫です。 (2)データサイズが不明な場合に適しています。