使用Emscripten如何将C ++ uint8_t数组获取到JS Blob或UInt8Array [英] Using emscripten how to get C++ uint8_t array to JS Blob or UInt8Array

查看:983
本文介绍了使用Emscripten如何将C ++ uint8_t数组获取到JS Blob或UInt8Array的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在emscripten C ++中,我有

In emscripten C++, I have

class MyClass {
public:
   MyClass() {}
   std::shared_ptr<std::vector<uint8_t>> buffer;
   int getPtr() {
      return (int)(buffer->data());
   }
   int getLength() {
      return buffer->size();
   }
};
EMSCRIPTEN_BINDINGS() {
    class_<MyClass>("MyClass").constructor()
      .function("getLength",&MyClass::getLength)
      .function("getPtr",&MyClass::getPtr,
                allow_raw_pointers());
}

我可以从JS调用getLength()和getPtr(),但我不知道如何让JS将其视为ArrayBuffer并下载为Blob。

I can invoke getLength() and getPtr() from JS but I'm don't know how to get JS to treat it as an ArrayBuffer for download as a Blob.

如何将缓冲区数据以一种可以获取的形式放入JS然后使用类似于 https:// github的代码下载它.com / kennethjiang / js-file-download / blob / master / file-download.js

How can I get the buffer data into JS in a form where I can then download it using code similar to https://github.com/kennethjiang/js-file-download/blob/master/file-download.js.

推荐答案

当前,WebAssembly仅定义基本数字类型以在JS和WASM之间进行通信。没有对象类型或数组类型。 这是WebAssembly的设计目标。 Emscripten进行了一些破解,使C ++ Class< => JS绑定,但是它们不是WASM标准。

Currently WebAssembly only defines basic number types to communicate between JS and WASM. There is no Object types nor Array types. This is the WebAssembly's design goal. Emscripten have done some hacks to make C++ Class <=> JS bindings, but they are not WASM standard.

但是有一种解决方法得到数组。即使没有API,JS也可以直接访问WASM模块的内部存储器。 WASM具有线性内存模型,并且线性内存通过 WebAssembly.Memory() WebAssembly.Memory()是单个ArrayBuffer WebAssembly.Memory.buffer ,其中WASM模块用作堆内存区域以及内存分配位置(例如 malloc())。

BUT there is a way around to get the array. JS have a direct access to the internal memory of WASM module, even without an API. WASM has a linear memory model and the linear memory is interfaced through WebAssembly.Memory(). WebAssembly.Memory() is a single ArrayBuffer WebAssembly.Memory.buffer where your WASM module uses as the heap memory region and where memory allocations (e.g. malloc()) happens.

这是什么意思?这意味着您从 getPtr()获得的指针(JS端的整数)实际上是 WebAssembly.Memory.buffer <的偏移量/ code>。

What does it mean? It means that the pointer (integer in JS side) you get from getPtr() is actually an offset to WebAssembly.Memory.buffer.

Emscripten自动生成JS(这是从名为 preamble.js )代码创建 WebAssembly.Memory()。您可以自己搜索Emscripten生成的代码,并且应该能够找到类似于此行

Emscripten automatically generates JS (this is generated from a template called preamble.js) code that create WebAssembly.Memory(). You can search Emscripten-generated code yourself and should be able find out a line similar to this line:

Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE });

因此,您可以通过 Module访问WASM模块使用的ArrayBuffer [ 'wasmMemory']。buffer

let instance = new Module.MyClass();

// ... Do something

let ptr = instance.getPtr();
let size = instance.getLength();
// You can use Module['env']['memory'].buffer instead. They are the same.
let my_uint8_buffer = new Uint8Array(Module['wasmMemory'].buffer, ptr, size);



2。 Emscripten HEAPU8



Emscripten提供将堆内存区域作为类型化数组访问的官方方法 HEAPU8 HEAPU16 HEAPU32 等定义为此处。因此,您可以这样做:

2. Emscripten HEAPU8

Alternatively, Emscripten offers an official way to access the heap memory region as typed arrays: HEAPU8,HEAPU16, HEAPU32, and etc. as defined here. So you can do like this:

let instance = new Module.MyClass();

// ... Do something

let ptr = instance.getPtr();
let size = instance.getLength();
let my_uint8_buffer = new Uint8Array(Module.HEAPU8.buffer, ptr, size);

使用 HEAPU8 会更安全,因为 HEAPU8 已记录在案,而 Module ['wasmMemory'] 的属性名却未作记录,可能会有所更改;但是他们做同样的事情。

Using HEAPU8 would be safer, since HEAPU8 is documented whereas the attribute name of Module['wasmMemory'] is kinda undocumented and may be subject to change; but they do the same thing.

Emscripten还提供了一个名为 emscripten :: val 供C ++开发人员在JS和C ++之间进行交互。为了方便起见,这将抽象任何JS / C ++类型。您可以使用此数组。

Emscripten also provides a class called emscripten::val for C++ developers to interact between JS and C++. This abstracts any JS/C++ types for convenience. You can get the array using this.

这是从文档和格伦的评论:

#include <emscripten/bind.h>
#include <emscripten/val.h>

emscripten::val getInt8Array() {
    return emscripten::val(
       emscripten::typed_memory_view(buffer->size(),
                                     buffer->data()));
}

EMSCRIPTEN_BINDINGS() {
    function("getInt8Array", &getInt8Array);
}

然后您可以调用 getInt8Array()

Then you can call getInt8Array() in JS side to get the typed array.

此处建议3个选项从WASM获得阵列。无论如何,我认为您应该了解 WebAssembly.Memory 的概念以及选项1的内容,因为这是从WASM中获取数组的最低级别,而且大多数重要的是,这是非托管且不安全的内存访问,因此在C / C ++端释放或修改对象时很容易破坏数据。对于这种特定情况,需要了解低级含义。

There are 3 options suggested here to get the array from WASM. In any way, I think you should understand the concepts of WebAssembly.Memory and things behind option 1, because this is the lowest level to get an array from WASM, and, most importantly, this is unmanaged and unsafe memory access so that it's easy to corrupt data when the object is freed or modified in C/C++ side. The knowledge of the low-level implications is required for this specific case.

这篇关于使用Emscripten如何将C ++ uint8_t数组获取到JS Blob或UInt8Array的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆