Passing ndarrays between Javascript and Rust

Hi All,

I’m very new to Rust, and I’m exploring it as an option to speed up some slow ndarray operations that I currently have on Javascript. I followed a tutorial (https://www.youtube.com/watch?v=WE33Q8GzTkU) and added this Rust function:

#[no_mangle]
pub fn add_numbers(x: i32, y: i32) -> i32 {
    x + y
}

and this JS call:

let t = async() => {
          const response = await fetch("http://localhost:8080/assets/number_adder.wasm");
          const buffer = await response.arrayBuffer();
          const obj = await WebAssembly.instantiate(buffer);
          console.log(obj.instance.exports.add_numbers(1, 2));  // "3"
        };
t();

So far everything works great, passing to integers x,y and getting the integer sum. The problems began when I tried to pass arrays from JS to RUST. I tried all sorts of combinations, but nothing seems to work.

Ideally, I would pass JS multidimensional array to a Rust ndarray, perform calculations and return some float number as an answer. If I could pass a reference to the array and not have to clone it, it would be super!
Can you help me with a basic example?
Thanks!

JS doesn’t have multidimensional arrays. It only has array-of-arrays (AKA jagged arrays). For Rust, or even WASM in general, the best layout would be to have contiguous chunk of memory to represent a multidimensional array (where arr2d[y][x] is actually arr1d[x + y*width]).

Unfortunately, there is no cheap way to convert from and to JS’s nested arrays, so if your problem has enough data to need WASM to help crunch it, you should avoid JS arrays, as that will require conversion “the hard way” by iterating all of the arrays-in-arrays and writing them to contiguous memory somewhere.

If you have an ArrayBuffer, use it directly. WASM likes dumb meaningless bytes, and communication with JS doesn’t actually support properly structured objects.

1 Like