1

Here's my C code:

// helloworld.c
#include <stdio.h>
#include <emscripten.h>

int* EMSCRIPTEN_KEEPALIVE getIntArray(){
    static int numbers[] = {1, 2, 4, 8, 16};
    return numbers;
}

Here's some of my JS:

// helloworld.html
let result = Module.ccall('getIntArray', // name of C function
  'Uint8Array', // return type
  [null], // argument types
  [null]); // arguments

let array = new Uint8Array(result,5);

console.log(result); // prints 1024
console.log(array); // prints Uint8Array(1024) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ]

All of this compiles and runs fine. The above code works fine for primitive values, but fails with the array pointer, and the JS typed array I get back is all zeros. I have seen some other solutions in the documentation, but they don't seem to work for me either.

4
  • Your function returns a pointer which is an integer instead of an array. In fact there is no array types in C. You will need to access the heap to get the wanted section out of the memory. To make things easier, there is an npm module that can be used to deal with arrays. Commented Sep 28, 2018 at 2:50
  • Changed my C function to this, same result: int8_t* EMSCRIPTEN_KEEPALIVE getIntArray(){ static int8_t numbers[] = {1, 2, 4, 8, 16}; return &numbers[0]; } Commented Sep 28, 2018 at 3:07
  • Well your new code is equivalent to your previous code snippet, so nothing will change. (&numbers[0] is equivalent to &*(numbers + 0)) But the point is, your function returns an address, not an array. Commented Sep 28, 2018 at 3:09
  • OK - so I think the problem is on the JavaScript side - I'll take a look at the npm module you linked to - thanks Commented Sep 28, 2018 at 3:34

1 Answer 1

3

You getIntArray function is going to return an integer which is the location of the array in the WebAssembly modules linear memory. In order to use this, you will need a reference to the module's linear memory.

One option is to create the linear memory on the JavaScript side:

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

  const instance = new WebAssembly.Instance(module, imports);

You can then use the returned result, which will be an integer, as an offset into linear memory:

 const result = Module.ccall('getIntArray', // name of C function
  'Uint8Array', // return type
  [null], // argument types
  [null]); // arguments

  const data = new Uint8Array(imports.env.memory.buffer, result, 5);
Sign up to request clarification or add additional context in comments.

2 Comments

That last line const data = new Uint8Array(imports.env.memory.buffer, result, 5); did it - thanks so much!
This is a great explanation! Do you know where/if this is documented?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.