在Rust Web程序集中访问UInt8ClampedArray

时间:2017-10-23 17:02:33

标签: javascript rust emscripten webassembly

我想将一个包含imageData的数组从Canvas传递给Rust函数,以便用它进行一些计算。我已将返回类型设置为null,以获取单向数据传递给工作:

JS

wasm.initialize({ noExitRuntime: true }).then(module => {
  const printImageData = module.cwrap("print_image_data", null, ["array"]);
  const functions = { add, printImageData };
  main(functions);
});


async function main(wasmFn) {
  const imageData = await getImageData();
  const data = new Uint8Array(imageData.data);
  wasmFn.printImageData(data);
}

#[no_mangle]
pub fn print_image_data(data: *mut [u8]) -> i32 {
    println!("{:?}", data);
    32
}

执行此操作时,我在浏览器控制台中收到以下错误:

thread 'main' panicked at 'cannot access stdout during shutdown', /checkout/src/libcore/option.rs:819:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.
uncaught exception: 5261184

如何从Rust端访问数组?那我怎么能再从JavaScript访问这些数据呢?我已经读过,传回一个数组是不可能的。

修改

the docs of emscripten我发现了以下内容:

  

argTypes - 函数参数类型的数组(如果没有参数,则可以省略)。类型与returnType一样,但不支持该数组,因为我们无法知道数组的长度。)

还有其他办法吗?也许通过指针并以某种方式访问​​数组?我觉得很难找到文档,所以任何链接都值得赞赏:)

1 个答案:

答案 0 :(得分:1)

这是一种基于this code访问fetch('hello_world.gc.wasm') .then(r => r.arrayBuffer()) .then(r => WebAssembly.instantiate(r)) .then(r => r.instance.exports) .then(wasm => { const width = 1; const height = 1; const byteSize = width * height * 4; let pointer = wasm.alloc(byteSize); let usub = new Uint8ClampedArray(wasm.memory.buffer, pointer, byteSize); let img = new ImageData(usub, width, height); wasm.abcd(pointer, width, height); console.log(`${img.data[0].toString(16)}`); console.log(`${img.data[1].toString(16)}`); console.log(`${img.data[2].toString(16)}`); console.log(`${img.data[3].toString(16)}`); }); 的方法。

<强>的JavaScript

use std::mem;
use std::os::raw::c_void;
use std::slice;

// In order to work with the memory we expose (de)allocation methods
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *mut c_void {
    let mut buf = Vec::with_capacity(size);
    let ptr = buf.as_mut_ptr();
    mem::forget(buf);
    return ptr as *mut c_void;
}

#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut c_void, cap: usize) {
    unsafe {
        let _buf = Vec::from_raw_parts(ptr, 0, cap);
    }
}

#[no_mangle]
pub extern "C" fn abcd(pointer: *mut u8, width: usize, height: usize) {
    let bytesize: usize = width * height * 4;
    let sl = unsafe { slice::from_raw_parts_mut(pointer, bytesize) };

    // Now you can change your buffer
    sl[0] = 0xaa;
    sl[1] = 0xab;
    sl[2] = 0xac;
    sl[3] = 0xad;
}

<强>锈

arangodb