Your question is very similar to this : WebAssembly supports only i32
/ i64
/ f32
/ f64
type values , as well as i8
/ i16
for storage.
This means that you cannot pass pointers. What you do is absolutely reasonable when you go from a C ++ point of view (no need to apologize for not knowing!), But that’s not how the WebAssembly border works. This is surprising for C ++ experts.
As in the lowercase question, you need to either:
- Copy the array one at a time, calling export once for each record (for example,
set(size_t index, int value)
). - Select the heap of the WebAssembly instance as an
ArrayBuffer
for JavaScript and write directly to the ArrayBuffer
values you want.
You can do the latter with the same code that I suggested in another answer:
const bin = ...; // WebAssembly binary, I assume below that it imports a memory from module "imports", field "memory". const module = new WebAssembly.Module(bin); const memory = new WebAssembly.Memory({ initial: 2 }); // Size is in pages. const instance = new WebAssembly.Instance(module, { imports: { memory: memory } }); const arrayBuffer = memory.buffer; const buffer = new Uint8Array(arrayBuffer);
From C ++ you are probably wondering: “But how do pointers work?”. Above, I explain that WebAssembly ↔ JavaScript, you cannot pass pointers! WebAssembly pointers provide simple i32
values. Empscripten relies on LLVM to do this, and since WebAssembly presents itself as ILP32 with a maximum 4GiB heap size, it just works.
It has interesting implications for indirect function calls and function pointers! I will leave this for another question :-)
However, this means that JavaScript can "talk" about pointers to WebAssembly: i32
is i32
. If you know that the value is somewhere on the heap, you can pass this i32
to JavaScript, and JavaScript can change it and pass it back to WebAssembly. If JavaScript has access to the ArrayBuffer
heap, then having i32
allows you to find out where the heaps are and change the heap as it would in C ++.
The WebAssembly heap is different from most C ++ heaps: it does not have access to executable pages and does not have access to the call stack (or rather, most of the call stack: compilers, such as LLVMs, can spill some values accepted by addresses instead of using local WebAssembly sites.) This is basically what Harvard architectures do (unlike von Neumann).
So what does your hello._array_add(result, a, b)
do? Extruding a
and b
from arrays using ToInteger
. This becomes 0
, which in WebAssembly is a valid heap place! You get a very unexpected part of your heap!