不复制地将JS ArrayBuffer或TypedArray传递给Emscripten

25

我在JavaScript中有一个非常大的ArrayBuffer(或TypedArray),我想将其传递给emscriptened函数。 我想传递原始字节而不产生副本。

如果我的C / C ++函数需要一个std :: string,如下所示:

void processBuffer(std::string const& buffer)

我可以获取数据,但如果我理解正确,将其转换为 std::string 将会导致缓冲区的复制。

有没有一种方法可以在不复制的情况下传递原始缓冲区?
我的访问权限仅限于只读。

我尝试过:

void processBuffer(const char* str, size_t size);

EMSCRIPTEN_BINDINGS中设置allow_raw_pointers(),但似乎不起作用。
我错过了什么吗?


在JS中,var ptr = Module._malloc(bytes); new Uint8Array(Module.HEAPU8.buffer, ptr, bytes); 这种写法不是更好吗?相比之下,new Uint8Array(bytes) 好像没有这么高效。 - zakki
1
是的。如果缓冲区是通过 Module._malloc() 分配并直接传递给期望 char* ptr 的 asm.js 函数,它将不会产生复制(正如在 emscripten 论坛上友好地向我解释的那样)。稍后会发布完整答案。 - Adi Shavit
@zakki 当从网络读取数据或写入HTML5画布时,您无法使用预分配的缓冲区;缓冲区由浏览器分配。令人困惑的是,emscripten似乎没有一种直接访问本机JS对象的方法,即使在EM_ASM块内也是如此。 - HRJ
你是否已经看过https://dev59.com/fGMm5IYBdhLWcg3wFL7s? - j4x
1个回答

6

回答自己。
目前为止,没有办法让emscriptened的C/C++代码访问JS分配的内存缓冲区。

话虽如此,通过Module._malloc()分配的缓冲区在使用C API时可以通过“指针”传递。

Embinding会向C++类型中添加额外的复制操作。

有关更多信息,请参见emscripten邮件列表上线程。


我倾向于认为这可以通过文件系统 API 实现。 - Jason Rice
我对此不是很熟悉。你是什么意思?另外请注意,自提问和编写以来可能发生了变化,特别是WASM的发布。 - Adi Shavit
我知道你可以在WorkerFS中加载文件blob,但是似乎没有支持任意ArrayBuffer的功能(在文件系统API中)。将它们作为文件访问似乎是可行的,也许应该添加这个功能。 - Jason Rice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接