How to return structs, Result, Option from Rust in WASM?

150 views Asked by At

This question is based on this discussion. I need to return different structures, Option, Result. I noticed the externalref crate, but it is in experimental status and I can't use it.

I was trying to do something like this:

#[repr(C)]
pub struct WasmResult {
    pub ok: i32,
    pub err_len: usize,
    pub err_ptr: *const u8,
}

#[no_mangle]
pub extern "C" fn test_string() -> WasmResult {
    let error_message = "An error message from Rust";
    let error_bytes = error_message.as_bytes();

    WasmResult {
        ok: 0,
        err_len: error_bytes.len(),
        err_ptr: error_bytes.as_ptr(),
    }
}

Host:

use anyhow::Result;
use wasmtime::*;
use wasmtime_wasi::WasiCtxBuilder;

#[repr(C)]
pub struct WasmResult {
    pub ok: i32,
    pub err_len: usize,
    pub err_ptr: *const u8,
}

fn main() -> Result<()> {
    println!("Compiling module...");
    let mut config = Config::new();
    config.wasm_reference_types(true);
    let engine = Engine::new(&config)?;
    let module = Module::from_file(&engine, "../target/wasm32-unknown-unknown/release/rust_wasm.wasm")?;

    println!("Initializing...");
    let linker = Linker::new(&engine);
    let wasi = WasiCtxBuilder::new()
        .inherit_stdio()
        .inherit_args()
        .expect("should always be able to inherit args")
        .build();
    let mut store = Store::new(&engine, wasi);

    let instance = linker.instantiate(&mut store, &module)?;

    let Ok(test_len) = instance.get_typed_func::<(), WasmResult>(&mut store, "test_string") else {
        anyhow::bail!("Failed to get WasmResult");
    };
    let test_string = test_len.call(&mut store, ())?.unwrap();

    Ok(())
}

I also tried to do this with wasmtime::ExternRef, but I don't know how I can implement the logic in the crate built into wasm without using the externref crate.

I also want to note that I need to call wasm functions from Rust, not from Js.

0

There are 0 answers