Как вы вызываете функцию C, которая получает (или возвращает) структуру по значению из JS через Emscripen / Wasm?

1

Передача структур, массивов и строк по ссылке с 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 для этого? Где это документировано?

Теги:
webassembly
emscripten

1 ответ

2

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);
  • 0
    Я действительно не хочу писать обертку (это огромный интерфейс C, так что это было бы больно). Если я сделаю это, я могу написать обертку, которая передается по ссылке. Любая идея, что делает Embind под капотом, который позволяет передавать по значению? (или это просто проход по ссылке под капотом)
  • 0
    И writeArrayToMemory и _malloc помогают, только если вы передаете по ссылке, верно? Вы не можете передать по значению, не получив доступ к стеку, или я что-то упустил?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню