Passing double arrays between functions in asm.js

冷暖自知 提交于 2019-12-02 01:58:18

问题


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:

  1. How do I correctly pass in a double array into an asm.js function?
  2. 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 _malloced 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!