Hello,
We have a way to use a linker to add a WASI module.
However, from what I can tell this method: wasmtime_linker_module(linker, &empty, _module)
magically instantiates the module.
As it is shown in the wasi.c example, calling the default method just works, without having a module instance.
https://github.com/bytecodealliance/wasmtime/blob/3715e19c67ab7e59fadf750a1de2ba48f1e6f4ce/examples/wasi/main.c#L84
I didn't manage to find a way on how to tell what the default method is (it seems to be fn main() ) for a main.rs
compiled with cargo build --target wasm32-wasi
. But in case of a lib that has a:
#[no_mangle]
pub extern "C" fn main() {`
This main
is not considered a default method. That's fine. It's surprising that I could call in a function returned by wasmtime_linker_get_default
that is non-null in my lib case. So who knows what that called into, but it's not my main function :D.
That being said, I would like to get my exports and find the fn main()
somwhere in the export list. Is there some example code somewhere that can show me how this is done?
Also would calling wasmtime_linker_instantiate(...)
instantiate my module twice? (as wasmtime_linker_module
seems to do that already).
I've found:
wasm_extern_vec_t externs;
wasm_instance_exports(instance, &externs);
assert(externs.size == 1);
wasm_func_t *gcd = wasm_extern_as_func(externs.data[0]);
assert(gcd != NULL);
But these are some opaque data structures and I can't tell what the names of the methods are.
I'd love to know the answer to it as well for my pet project wasmtime-zig. From some prelim research, but @Alex Crichton can correct me here, I think we could search for an export by name using wasmtime_caller_export_get
. As far as an example is concerned, I'm following @Alex Crichton's excellent wasmtime-go integration. In particular, here's the shim which wraps wasmtime_caller_export_get
in Go: https://github.com/bytecodealliance/wasmtime-go/blob/main/shims.c#L28 Is that what you're after BTW?
How did you create the wasmtime_caller_t*?
What I tried was:
wasm_func_t* func = nullptr;
wasm_name_t name;
wasm_name_new_from_string(&name, "main");
auto error = wasmtime_linker_get_default(_linker, &empty, &func);
This gets me back a method, but I am almost certain it's not the correct one, as it doesn't print anything and doesn't trigger any breakdpoint in the rust code that was used to compile it.
The interesting thing is that using any random string in wam_name_new_from_string(&name, "randomstuff");
, is absolutely fine and I do still get a func back that's not nullptr that I can call with wasmtime_func_call(
Oh, wait, that name is not the function name, but the module name from where the _default_ function is returned.
It's not nullptr as the default is (in linker.rs
):
// Otherwise return a no-op function.
Ok(Func::new(
&self.store,
FuncType::new(Vec::new().into_boxed_slice(), Vec::new().into_boxed_slice()),
move |_, _, _| Ok(()),
))
@Alexandru Ene FWIW dealing with the "default export" is mostly for wasi things
if your modules use wasi then you'll want to use that, otherwise you'll likely want to use the wasmtime_linker_instantiate
API to get an instance back out
otherwise there's Rust APIs for getting items from a Linker
, but they may not be bound in the C API yet
So I want to have a method, that works with WASI and can have a way of returning wasm_func_t functions for things I marked as "extern C" in rust (the thing that's compiled to WASM).
It's fine for now to say that it needs to be a main()
from a rust binary. But I am not sure how to extract from a module functions that need WASI and a linker.
I would have expected that get_function to return nullptr if it's not found tho, it's slightly confusing it returns a no-op
@Alexandru Ene the simplest thing to do today would be to make a wasmtime_linker_t
, add wasi to it, then call wasmtime_linker_instantiate
to get a wasm_instance_t
then you can iterate over the exports and work with the module
that doesn't handle the reactor/command difference right now, but that's a relatively new concept and may not need to be handled by you just yet
That seems great. I wasn't sure if wasmtime_linker_instantiate
would duplicate the instance as wasmtime_linker_module
seems to create an instance under the hood (without exposing it to C)
Thanks for all the help Alex
oh it would duplicate the instance
wasmtime_linker_module
registers a module to be instantiated by the linker automatically under a given name
whereas wasmtime_linker_instantiate
will create a new instance and return it, not registering anything with the linker
Oh great then. Like this it does exactly what i need. I thought the call to wasmtime_linker_module
was mandatory. If I can use linker_instrantiate instead it's perfect
ah yeah wasmtime_linker_module
is just optional!
As for linker.rs
, get_default(), it should probably return an Err() if there's no default method, having a no-op as the default makes kind of hard on the users of the library to figure out why things don't work as expected and there are probably not so many cases when that's actually desirable (running a no-op method).
The signature is already pub fn get_default(&self, module: &str) -> Result<Func> {
Last updated: Dec 23 2024 at 12:05 UTC