How to access WebAssembly linear memory from C/C++

What you need to do is communicate a location within the WebAssembly module that both the C and JavaScript code read / write to.

Here's a simple example that adds a number to each element in array. This is the C code:

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];
}

The important thing in the above code is the int* getData() function, which returns a reference to the start of the data array. When compiled to WebAssembly, this will return an integer which is the location of the data array within the modules linear memory.

Here's an example of how to use it:

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]);
}

You can see the complete example in this WASM fiddle.


There are 2 opposite approaches:

  1. Declare all your data elements as globals and add helper functions to return begining address for each.
  2. Don't use globals, allocate desired Memory in JS, calculate offsets and pass those offsets to called functions. In this case available memory will start from 0 (zero).

(1) is ok for simple things. (2) is suitable when your data size is unknown.