我正在从Unity3D WebGL上下文中将几kB的数据(生成的PNG文件)传递给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'});
它们两者都应该比原始代码快得多,并且两者应该具有完全相同的性能。这是因为他们直接从Blob
创建了一个新的HEAPU8
,而没有像原始代码那样创建重复的数组。
HEAPU8
是Uint8Array
,是TypedArray系列之一。关于TypedArray的一个真正重要的事情是,它实际上不是缓冲区/数据,而是保存实际数据的基础ArrayBuffer(它是HEAPU8.buffer
)对象的“ view”。参见ArrayBufferView
。
因此ArrayBufferView
为HEAPU8
ArrayBuffer对象(特别是Emscripten中的HEAPU8.buffer
)提供了一个看起来像uint8_t数组的接口。 Emscripten还提供了HEAPU16,HEAPU32,HEAPF32等,但是它们具有相同的ArrayBuffer,但具有不同的视图。
WebAssembly.Memory.buffer
和WebAssembly.Memory.buffer
要做的是创建具有指定范围的ArrayBuffer对象的新“视图”,而不是复制缓冲区。因此,您将获得最低的性能损失。