Recursion is weird, so i will try to explain this in as few words as possible.
I want to register a host fn which can take a wasm fn as argument.
and i want that argument (wasm fn) to also be able to take a fn as an argument so that i can recursively call it if needed so which itself might call into the original host fn and so on...
I am basically looking into egui + wasm scripting. egui uses a heavy closure based api like
Window::new("hello window").show(|ui| {
ui.button("top ui");
ui.horizontal(|hui| {
hui.label("horizontal ui label");
hui.child_ui(|cui| {
cui.label("inner child ui");
});
});
});
here, show
is a host fn, and this wasm closure needs to be called by that fn with ui as argument. and ofcourse, all the button/horizontal/child_ui/label fns are host bindings too.
so, to provide those bindings, i need to take wasm closures and wasm closures might call host bindings (like child_ui
or horizontal
) recursively.
I am thinking that its not possible, but wanted to ask here just in case.
This is all theoretically possible with building blocks in the Wasmtime API. For example if you'd like you can use the funcref
type which is Option<Func>
as an argument. Both a wasm and a host function can become a Func
. Few wasm guests have native support for funcref
, though, so an analogue would instead be to communicate with indices that are actually indexes into a Table
where the host can store functions in there along with the guest.
Your hardest part, however, is likely going to be wrangling mutability. Invocations of wasm require &mut Store<T>
which means that you have to thread that all the way from when the host was called into back to where the wasm is being invoked. If this is spread out across an application that probably won't work too well, but if it's a local decision it may be easier.
In any case what you want is possible in theory, but you may run into limitations trying to wrangle this all into Rust (as I'm sure the egui folks did as they designed APIs in Rust too!)
Few wasm guests have native support for funcref
can rust as a guest turn a closure into funcref
?
a funcref
is akin to a function pointer, so no, it doesn't have data associated with that. If you need data then you would need to forward that along through arguments
Is there any way you could pass a more complex type to a host function or set it on the store from within the wasm module? What's really the "standard" way to get data back from a module when running it with wasmtime? Just beeing able to pass a json-serialized string in between would be a huge benefit.
I did attempt to pipe stdout as described in the link @Dan Gohman was kind enough to provide, but without luck. After dropping the store and printing the contents there was just an empty vector. Will it pipe return-values from the functions in wasm or should I explicitly write to stdout from inside the module like io::stdout().write_all(b"hello world")?;
?
you most likely would want to use interface types and optimally the component model, but I would honestly suggest to give them air to breathe, the way in which you load and call complex functions (returning more than u32) is being fleshed out right now, Dan mentioned he thinks he should have a working example to showcase around March :)
Ramon Klass said:
you most likely would want to use interface types and optimally the component model, but I would honestly suggest to give them air to breathe, the way in which you load and call complex functions (returning more than u32) is being fleshed out right now, Dan mentioned he thinks he should have a working example to showcase around March :)
I see, wow, that's a fantastic spec! Looking forward to see that in place :)
In the meantime, i suppose reading/writing into shared memory would be the way to go to pass more complex types in between rust and wasm? I'm thinking I may give that a go for now. I found the wasmtime Memory
documentation, so I can probably figure out how to pass stuff in and how to read them out - but I'm not sure how to interact with the memory inside the wasm module - grateful for any tips that might help
This looks like an example of reading/writing to a shared memory buffer - right?
https://wasmbyexample.dev/examples/webassembly-linear-memory/webassembly-linear-memory.rust.en-us.html
Last updated: Nov 22 2024 at 16:03 UTC