通过WASM构建新的Rust Vec时,JavaScript ArrayBuffer“分离”

use*_*246 4 javascript rust webassembly

基本思想是返回一个指针,然后Vec在每个视频帧上创建一个指针后,将使用该指针显示图像:

JavaScript:

var ptr = exports.alloc(size);
let bytes = new Uint8ClampedArray(exports.memory.buffer, ptr, size);
let image = new ImageData(bytes, 320, 240);

function tick() {
    requestAnimationFrame(tick);
    ctx.drawImage(video, 0, 0, width, height);
    let imageData = ctx.getImageData(0, 0, width, height).data;
    bytes.set(imageData);
    exports.create_vector();
    ctx.putImageData(img, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

锈:

var ptr = exports.alloc(size);
let bytes = new Uint8ClampedArray(exports.memory.buffer, ptr, size);
let image = new ImageData(bytes, 320, 240);

function tick() {
    requestAnimationFrame(tick);
    ctx.drawImage(video, 0, 0, width, height);
    let imageData = ctx.getImageData(0, 0, width, height).data;
    bytes.set(imageData);
    exports.create_vector();
    ctx.putImageData(img, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

这是实际的代码

这是错误消息:

铬:

#[no_mangle]
pub extern "C" fn alloc(capacity: usize) -> *mut c_void {
    let mut buf = Vec::with_capacity(capacity);
    let ptr = buf.as_mut_ptr();
    mem::forget(buf);
    return ptr as *mut c_void;
}

#[no_mangle]
pub extern "C" fn create_vector() {
    let _: Vec<u8> = Vec::with_capacity(320 * 240);
}
Run Code Online (Sandbox Code Playgroud)

苹果浏览器:

Uncaught TypeError: Cannot perform %TypedArray%.prototype.set on a detached ArrayBuffer
    at Uint8ClampedArray.set (<anonymous>)
    at tick
Run Code Online (Sandbox Code Playgroud)

Mozilla:

This webpage was reloaded because a problem occurred
Run Code Online (Sandbox Code Playgroud)

罪魁祸首似乎是:

let bytes = new Uint8ClampedArray(exports.memory.buffer, ptr, size);
// ...
    exports.create_vector();
// ...
Run Code Online (Sandbox Code Playgroud)

即,当我尝试ptr在调用后再次使用时,浏览器崩溃exports.create_vector

这是怎么了?有解决方案吗?

小智 5

当您分配新缓冲区并且WASM“进程”没有为其分配足够的内存时,浏览器将分配一个更大的新缓冲区,并将所有数据从旧位置复制到该缓冲区中。在WASM解释器中,它非常透明,但是传递给JavaScript(您使用构造Uint8ClampedArray)的所有指针都会失效。据我所知,有两种解决方案:

  • 初始化时在WASM“进程”中分配足够的内存,并立即对其进行分配,以便只要内存使用率低于所选大小,指针就不会失效。
  • 跟踪传递给JavaScript的缓冲区以及此类错误的“更新”指针。