Передача структур, массивов и строк по ссылке с Javascript на C довольно хорошо документирована в документах Emscripten (https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html# взаимодействия с кодом-direct-function-calls).
Но как насчет передачи структур по стоимости? Если у меня есть функция C, например:
typedef struct {double a, b, c;} MyStruct;
MyStruct Foo(const MyStruct x, double y);
Как я могу назвать Foo и декодировать результат? (Либо используйте Module.cwrap, либо напрямую вызывайте Module._Foo). Должен ли я получить доступ к стеку Emscripten для этого? Где это документировано?
Module._malloc()
, Module.writeArrayToMemory()
и Module.ccall()
доступны, но это очень сложно.
Легче обернуть его C++ и замалчивать.
// em++ --bind test.cpp -o test.js
#include <emscripten.h>
#include <emscripten/bind.h>
using namespace emscripten;
struct MyStruct {
double a, b, c;
};
MyStruct Foo(const MyStruct x, double y) {
MyStruct r;
r.a = x.a;
r.b = x.b;
r.c = y;
return r;
}
EMSCRIPTEN_BINDINGS(my_struct) {
class_<MyStruct>("MyStruct")
.constructor<>()
.property("a", &MyStruct::a)
.property("b", &MyStruct::b)
.property("c", &MyStruct::c)
;
function("Foo", &Foo);
}
И звоните из JavaScript.
var x = new Module.MyStruct();
x.a = 10;
x.b = 20;
x.c = 30;
var y = Module.Foo(x, 21);
console.log(y, y.a, y.b, y.c);
x.delete();
y.delete();
Также вы можете выделить память в стеке и ccall
.
var sp = Module.Runtime.stackSave();
var ret = Module.allocate(24, 'i8', Module.ALLOC_STACK);
var ptr_a = Module.allocate(24, 'i8', Module.ALLOC_STACK);
Module.HEAPF64[(ptr_a >> 3) + 0] = Math.random();
Module.HEAPF64[(ptr_a >> 3) + 1] = Math.random();
Module.HEAPF64[(ptr_a >> 3) + 2] = Math.random();
Module.ccall("Foo",
'number',
['number', 'number', 'number'],
[ret, ptr_a, 21]
);
console.log(
sp,
Module.HEAPF64[(ret >> 3) + 0],
Module.HEAPF64[(ret >> 3) + 1],
Module.HEAPF64[(ret >> 3) + 2]);
Module.Runtime.stackRestore(sp);