要将类型化数组从 emscripten'ed C++ 传递给 javascript,我想出了这段代码
#include <emscripten/bind.h>
#include <emscripten/val.h>
auto test(const emscripten::val &input) {
const auto data = emscripten::convertJSArrayToNumberVector<float>(input); // copies data
// generate output in some form
std::vector<float> output = { 1, 2, 3 };
// make a typed array view of the output
emscripten::val view{ emscripten::typed_memory_view(output.size(), output.data()) };
// create new typed array to return
auto result = emscripten::val::global("Float32Array").new_(output.size());
// copy data from generated output to return object
result.call<void>("set", view);
return result;
}
EMSCRIPTEN_BINDINGS(KissFft) {
emscripten::function("test", &test);
}
(用 构建em++ test.cpp -o test.html --bind
)
在这种情况下,有两个额外的副本:
- 据我所知,从输入数组到 wasm 内存的复制是不可避免的;
const auto data = emscripten::convertJSArrayToNumberVector<float>(input);
- 从 wasm 内存复制到 javascript 对象:
emscripten::val view{ emscripten::typed_memory_view(output.size(), output.data()) }; auto result = emscripten::val::global("Float32Array").new_(output.size()); result.call<void>("set", view); return result;
在第二种情况下,有没有办法避免从生成的输出到 javascript 对象的额外复制?
我知道像这样返回内存视图的可能性:
std::vector<float> output;
auto test(const emscripten::val &input) {
const auto data = emscripten::convertJSArrayToNumberVector<float>(input);
//generate output
return emscripten::val{ emscripten::typed_memory_view(output.size(), output.data()) };
}
EMSCRIPTEN_BINDINGS(KissFft) {
emscripten::function("test", &test);
}
但在这种情况下,返回的对象指的是output
静态对象拥有的底层内存,并会产生所有后果,比如在 C++ 端修改内存,甚至释放它。