问题
I have a C function compiled into asm.js with the following parameters:
void myfunc(double v1[], double v2[], int v_size, double c)
It takes in an array (v1
), applies a transformation, then fills another array of the same size (v2
) with the output.
I compile it, and then run the following JS code:
v1 = new Array(1.0, 1.5, 2.0);
v2 = Module._malloc(8 * v1.length);
Module.ccall("myfunc", null, ["array", "number", "number", "number"], [v1, v2, v1.length, 2]);
However when I run getValue(v2, "double")
I get 1.297703e-318 (which is wrong), and when I run getValue(v2 + 8, "double")
or getValue(v2 + 16, "double")
it returns 0 (which is also wrong).
I've reduced the C function to just console log out the contents of v1
and it prints out garbage data as well, so at least there is an issue with reading a double array passed in. The more specific questions are:
- How do I correctly pass in a double array into an asm.js function?
- How do I correctly return a double array from an asm.js function?
回答1:
I'm a bit late to this, but for what it's worth...
When working with passing numeric types between JS and the Emscripten run-time I've found I've had to work with Uint8Array
type typed arrays, changing the view from another type if necessary. Something like this:
myfunc = Module.cwrap('myfunc', null, ['array']);
var v1 = new Float64Array([2.3, 4.2, 6.8, 8.9]);
var uarray = new Uint8Array(v1.buffer); // change the view to Uint8
// before passing
myfunc(uarray);
with a C function like this:
void mfunc(const double *v1)
{
printf("%f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
}
should see the values printed out. Note, if you try writing to the memory pointed to by v1 (obviously removing the const
first) and accessing v1
in the JavaScript, you'll notice that your changes are ignored, as ccall
and cwrap
use the stack for passing the array.
To alter an array on the C side, you need to use Module._malloc
to allocate some memory in the Emscripten run-time, this gives you a 'pointer' (treated as a number by JavaScript and referred to as a number in cwrap
) which you can read and write from. You can use Module.getValue
to 'dereference' the pointer:
myfunc = Module.cwrap('myfunc', null, ['array', 'number']);
var v1 = new Float64Array([2.3, 4.2, 6.8, 8.9]);
var uarray = new UintArray(v1.buffer);
var ptr = Module._malloc(v1.byteLength);
myfunc(uarray, ptr);
for (var i=0; i<v1.length; i++)
{
console.log(Module.getValue(ptr+i*v1.BYTES_PER_ELEMENT, 'double'));
}
and a C function like this:
void mfunc(const double *v1, double *v2)
{
printf("%f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
int i = 0;
for (i = 0; i < 4; i++)
{
v2[i] = 2 * v1[i];
}
}
Should see a list of the values of v1 being doubled and printed on the browser JS console.
Obviously, you could also pass the array into myfunc
using a similar method, but you have to clean up any _malloc
ed data, so I tend to avoid doing that for values I want don't want to alter.
来源:https://stackoverflow.com/questions/38060714/passing-double-arrays-between-functions-in-asm-js