我将几 kB 的数据(生成的 PNG 文件)从 Unity3D WebGL 上下文传递到 javascript,以便用户可以在不离开 WebGL 上下文的情况下下载 PNG 文件。 Unity使用emscripten并将js嵌入为jslib。这是我第一次查看 emscripten 或在 js 中使用指针,在 emscripten 文档中找不到基础知识。
它可以工作,但我认为这是一个糟糕的实现,代码如下:
mergeInto(LibraryManager.library, {
JSDownload: function(filenamePointer, dataPointer, dataLength) {
filename = Pointer_stringify(filenamePointer);
var data = new Uint8Array(dataLength);
for (var i = 0; i < dataLength; i++) {
data[i]=HEAPU8[dataPointer+i];
}
var blob = new Blob([data], {type: 'application/octet-stream'});
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else{
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
});
令我困扰的是这样的单步执行数据,因为我已经有了地址和长度,所以我想在已知地址实例化“数据”数组,就像我在 C 中使用 * 和 & 一样,而不是复制它是一个字节一个字节地复制,或者如果我必须复制它,至少要一次点击而不是循环复制。我认为我最大的问题是不知道在哪里寻找文档。我通过查看 GitHub 上的随机项目发现了比这里更多的内容:https://emscripten.org/docs/api_reference/preamble.js.html
如有任何帮助,我们将不胜感激,谢谢。
最佳答案
所以你不喜欢这部分?
var data = new Uint8Array(dataLength);
for (var i = 0; i < dataLength; i++) {
data[i]=HEAPU8[dataPointer+i];
}
var blob = new Blob([data], {type: 'application/octet-stream'});
你可以把它写成一行:
var blob = new Blob([HEAPU8.subarray(dataPointer, dataPointer + dataLength)], {type: 'application/octet-stream'});
// or this
var blob = new Blob([new Uint8Array(HEAPU8.buffer, dataPointer, dataLength)], {type: 'application/octet-stream'});
它们都应该比您的原始代码快得多,并且它们都应该具有完全相同的性能。这是因为他们直接从 HEAPU8
创建一个新的 Blob
,而不像原始代码那样创建重复的数组。
HEAPU8
是一个 Uint8Array
,TypedArray 系列之一。关于 TypedArray 的一件非常重要的事情是,它实际上不是缓冲区/数据,而是底层 ArrayBuffer(它是 HEAPU8.buffer
)对象的一个“ View ”,该对象保存实际数据。请参阅ArrayBufferView
.
所以HEAPU8
为HEAPU8.buffer
ArrayBuffer对象提供了一个接口(interface),具体来说WebAssembly.Memory.buffer
在 Emscripten 中,看起来像一个 uint8_t 数组。 Emscripten 还提供了 HEAPU16、HEAPU32、HEAPF32 等,但它们具有相同的 ArrayBuffer 和不同的 View 。
.subarray(start, end)
和 new Uint8Array(buffer, offset, size)
的作用是创建 ArrayBuffer 对象的新“ View ”指定范围内,不复制缓冲区。因此,您的性能损失将降至最低。
关于javascript - 在 emscripten 中的已知堆地址处创建数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60106899/