在脚本中的已知堆地址处创建数组

问题描述 投票:0回答:1

我正在从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

任何帮助,谢谢。

javascript emscripten unity-webgl
1个回答
1
投票

所以您不喜欢这部分吗?

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,而没有像原始代码那样创建重复的数组。

HEAPU8Uint8Array,是TypedArray系列之一。关于TypedArray的一个真正重要的事情是,它实际上不是缓冲区/数据,而是保存实际数据的基础ArrayBuffer(它是HEAPU8.buffer)对象的“ view”。参见ArrayBufferView

因此ArrayBufferViewHEAPU8 ArrayBuffer对象(特别是Emscripten中的HEAPU8.buffer)提供了一个看起来像uint8_t数组的接口。 Emscripten还提供了HEAPU16,HEAPU32,HEAPF32等,但是它们具有相同的ArrayBuffer,但具有不同的视图。

WebAssembly.Memory.bufferWebAssembly.Memory.buffer要做的是创建具有指定范围的ArrayBuffer对象的新“视图”,而不是复制缓冲区。因此,您将获得最低的性能损失。

© www.soinside.com 2019 - 2024. All rights reserved.