2017-10-14 87 views
2

我正在编写一个小型C程序,旨在编译为wasm w/emcc并在Web浏览器中运行。因为wasm导出的函数只能接受简单的数字值作为参数输入和返回值,所以我需要在JavaScript API和编译的WebAssembly代码之间共享内存,以访问更复杂的数据类型,如字符串或数组。问题是我不能在我的生活中弄清楚如何从我的C程序中访问WebAssembly linear memory如何从C/C++访问WebAssembly线性内存

我的最终目标是能够读取在我的C程序中使用JavaScript初始化的字符串,然后还可以在Web浏览器的JavaScript代码中读取在我的C程序中修改/初始化的字符串。

这里是什么,我试图做一个简单的例子:

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

您需要做的是在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完整的例子。

0

有2点相反的方法:

  1. 声明你的所有数据元素作为全局,并添加辅助函数返回每个begining地址。
  2. 不要使用全局变量,在JS中分配所需的内存,计算偏移量并将这些偏移量传递给调用的函数。在这种情况下,可用内存将从0(零)开始。

(1)对于简单的事情没问题。 (2)适用于您的数据大小未知的情况。