2016-06-27 21 views
0

У меня есть функция C скомпилирована в asm.js со следующими параметрами:Передача двойных массивов между функциями в asm.js

void myfunc(double v1[], double v2[], int v_size, double c) 

Он принимает в массиве (v1), применяет трансформацию, затем заполняет другое массив того же размера (v2) с выходом.

Я скомпилировать его, а затем запустить следующий JS код:

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

Однако, когда я бегу getValue(v2, "double") я получаю 1.297703e-318 (что неправильно), и когда я бегу getValue(v2 + 8, "double") или getValue(v2 + 16, "double") возвращает 0 (что также неверно).

Я уменьшил функцию C, чтобы просто вывести из системы содержимое v1, а также распечатывает данные мусора, поэтому, по крайней мере, возникает проблема с чтением переданного двойного массива. Более конкретные вопросы:

  1. Как правильно передать двойной массив в функцию asm.js?
  2. Как правильно вернуть двойной массив из asm.js-функции?
+0

Должно ли ["массив", "число", "число", "число"] быть ["массив", "массив", "число", "число"]? – pah

+0

@threadp: Мне сказали об этом.js IRC, так как v2 не является массивом Javascript, я не должен использовать «массив» для его передачи, вместо этого использовать «число». – Lucas

+0

@ Лукас, в этом случае, почему нет [«число», «число», «число», «число»]? –

ответ

2

Я немного поздно, но для чего это стоит ...

При работе с прохождением числовых типов между JS и Emscripten во время выполнения я обнаружил, что я должен был работа с Uint8Array тип типизированных массивов, при необходимости изменив представление с другого типа. Что-то вроде этого:

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

с функцией C, как это:

void mfunc(const double *v1) 
{ 
    printf("%f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]); 
} 

должны увидеть значения распечатаны. Обратите внимание: если вы попытаетесь записать в память, указанную v1 (очевидно, сначала удалив const) и получив доступ к v1 в JavaScript, вы заметите, что ваши изменения игнорируются, так как ccall и cwrap используют стек для передачи массива.

Чтобы изменить массив на стороне C, вам необходимо использовать Module._malloc для выделения некоторой памяти во время выполнения Emscripten, это дает вам «указатель» (рассматривается как номер по JavaScript и называется числом в cwrap), с которого вы можете читать и писать. Вы можете использовать Module.getValue для «разыменования» указателя:

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

и функции C, как это:

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

должны увидеть список значений v1 удваиваются и распечатаны на браузере JS консоли ,

Очевидно, вы также можете передать массив в myfunc, используя аналогичный метод, но вы должны очистить любые данные _malloc, поэтому я стараюсь избегать этого, поскольку значения, которые я хочу, не хотят изменять.