This code worked a few months back but now it stopped working and I can't figure out why:
#[no_mangle]
pub fn simple_arr() -> *mut i32 {
let vec = &mut [111, 222, 333, 444];
return vec.as_mut_ptr();
}
fn main() {
println!("Hello, world!");
}
I am compiling the code using the following tools:
$ cargo +nightly build --target wasm32-unknown-unknown --release
$ wasm-gc target/wasm32-unknown-unknown/release/wasm-examples.wasm m.wasm
I then fire up a HTTP server and I run the following code in the browser:
fetch('m.wasm')
.then(r => r.arrayBuffer())
.then(r => WebAssembly.instantiate(r))
.then(m => window.m = m);
var HEAP32 = new Int32Array(m.instance.exports.memory.buffer);
var arrayPtr = m.instance.exports.simple_arr();
console.log(HEAP32[arrayPtr / Int32Array.BYTES_PER_ELEMENT]);
and I get 0. I keep getting 0 or random numbers even if I keep incrementing the offset/pointer.
I can't figure out what am I missing.
I also tried this form:
use std::os::raw::c_void;
#[no_mangle]
pub fn simple_arr() -> *mut c_void {
let mut vec = vec![100, 200, 300, 400];
vec.as_mut_ptr()
}
fn main() {
println!("Hello, world!");
}
but I still get the same result.
I also tried compiling it with Emscripten and still the same result.
Update:
I tried exposing a static string and that works (via How to return a string (or similar) from Rust in WebAssembly?). However exposing a vector seems different and I don't think this result applies to me.
I tried declaring the vector static
#[no_mangle]
pub fn simple_arr() -> *mut c_void {
static mut vec: &'static [i32] = &[100, 200, 300, 400];
unsafe { vec.as_mut_ptr() as *mut c_void }
}
but I can't get it to compile.
Update: I got it to work!!
#[no_mangle]
pub fn simple_arr() -> *const i32 {
let vec = &[100, 200, 300, 400];
vec.as_ptr() as *const i32
}
As far as I understand, the pointer lifetime ended right after the function was executed. So with const we extend the lifetime of that pointer.
Final update:
ok so the final final version is to expose a wrapped pointer from a Boxed vector:
#[no_mangle]
pub fn simple_arr() -> *mut i32 {
let vec = Box::new([100, 200, 300, 400]);
Box::into_raw(vec) as *mut i32
}
I hope this is the "non accidental" version. If not so please leave a comment.
Thanks everybody!