wasmerio / wasmer

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
https://wasmer.io
MIT License
18.28k stars 775 forks source link

Could someone please provide a self-contained, working wasi example, with proper dependency handling? #4650

Open TheQuantumPhysicist opened 2 months ago

TheQuantumPhysicist commented 2 months ago

Summary

Not a single example can work without issues, and version numbers are confusing.

Additional details

I have tried every combination of wasmer + wasi*.

https://github.com/wasmerio/wasmer/blob/bebb859446d4463b87a78ec053a72ade2f47b0b3/examples/wasi_manual_setup.rs

I've been tinkering for hours trying to just run an fn add(a: u32,b: u32) -> u32, and I can't just get this to compile. The features are confusing and the examples don't work, even if I clone the wasmer repo.

Could someone please just help me get my first example working in the correct way? All I want is a wasi example where I can run a wasm file and call a simple function.

syrusakbary commented 2 months ago

Hey @TheQuantumPhysicist , we just published a new version of Wasmer 4.3.0 which should be on-par with the example code (we are testing it as part of the CI).

Can you try the example again using Wasmer 4.3.0 and see if that fixes your issues? Thanks!

TheQuantumPhysicist commented 2 months ago

So, I successfully compiled the example on 4.3, thanks for fixing that.

But... I was unsuccessful in getting it to be useful. I have to say that many things are not documented and are hard to understand. Wasmer needs a dozen more examples for noobs like me to get how it works. And just to be fair, I'm not a noob programmer, I'm just noob in wasm.

In the time after I asked and gave up, I went to wasmtime and I was able to finish the prototype I was making much quicker.

The workflow in wasmtime makes more intuitive sense than wasmer IMHO. For example, for host functions, one instantiates a linker, and links imported functions to the module, and through trait magic, wasmtime can automatically detect the types of the function. Then, one can instantiate functions with instance.get_typed_func<Params, Return>(), which returns an object with a call method to do the calling into the wasm file.

In wasmer, I had to use the import method in env builder and I had to manually specify the types (not a big deal though, just an inconvenience), each with an enum, and when I finally got to the closure to specify the host function, I had to return a vector of wasm values for some reason (?), and worse of all, I couldn't find a way to call that function!

Then I looked at the second (manual) example where a function call exists, but then I had to include tokio for some reason (?), where I get a panic if no reactor exists... (why does running wasm need tokio runtime? It should be completely optional). So, I add tokio. Then I started to get linking issues again, saying something about my custom import function:

called `Result::unwrap()` on an `Err` value: Link(Import("SomeNamespace", "call_host_function_example", UnknownImport(Function(FunctionType { params: [], results: [] }))))

even though it was defined in the wasi_env:

    const VOID_TO_VOID: ([wasmer::Type; 0], [wasmer::Type; 0]) = ([], []);

    let mut wasi_env = WasiEnv::builder("hello")
        .import(
            "SomeNamespace",
            "call_host_function_example",
            wasmer::Extern::Function(wasmer::Function::new(
                &mut store,
                VOID_TO_VOID,
                move |_| -> Result<Vec<wasmer::Value>, wasmer::RuntimeError> {
                    host_fn();
                    Ok(vec![])
                },
            )),
        )
        .stdout(Box::new(stdout_tx))
        .finalize(&mut store)
        .unwrap();

    let import_object = wasi_env.import_object(&mut store, &module).unwrap();
    let instance = wasmer::Instance::new(&mut store, &module, &import_object).unwrap(); // <-- this errors, even though import_object has that definition

and whether I add it or remove it, doesn't matter. It just doesn't work. Somehow the host function is not being recognized in the instance. Note that the other simpler wasi example linking to this same wasm file/bytes worked, but it's useless to me because it can only pipe stdout/stdin as far as I understand, where I need more complex functionality for my application, like calling functions.

Please note that the same wasm file works fine with wasmtime, so either there's a bug or I'm doing something wrong that isn't obvious to me.

I'm definitely ignorant in all this, and please take what I'm saying as what a noob using your library will feel.