Open Froidoh opened 1 week ago
Hi! You did a lot of figuring things out in your journey to this point, in a brand new technology with docs we know could use some work, so great job so far. It looks like the bit missing here is that when hello
is in an interface called greetings
, so first you must get the greetings
instance out of your root instance: instance.exports(&mut store).instance("greetings").expect("root has greetings instance").typed_func("hello")
.
An alternative is to use wasmtime::component::bindgen!
in your host, which will generate, among other things, a TestPlugin
struct, which has typed, string-name-free methods to access all of the world's exports. You can use cargo doc --document-private-items
to see the extent of what that macro generates, or if WASMTIME_DEBUG_BINDGEN
is set during build, the generated code will be in OUT_DIR
. That generated code should be able to replace everything in your host from println!(have linker) down.
The other reason to recommend bindgen is that wasmtime 23 will change the way instance exports work in order to make reuse more efficient, so the answer in the first paragraph will need to be rewritten (https://docs.wasmtime.dev/api/wasmtime/component/struct.Instance.html, you'll need to call, pardon shorthand, get_typed_func(get_export(get_export("greetings"), "hello"))
)
One final suggestion - its fine to file issues like these, and also we invite this sort of question / debugging journey on https://bytecodealliance.zulipchat.com/.
@pchickey thanks for taking the time to answer!
The problem with the macro approach is that I want to write a dynamic plugin system, so I don't know the wasm components aka plugins that are available at runtime.
I would definitely prefer the "non stringified function calls" but, correct me if wrong, that's currently not possible then.
What I would need to get this dynamically at runtike working is something like a "interpret this component as an instance of this (rust) trait" or a "cast" so to speak
The bindgen! happens at rustc compile time, yes, so you have to know the world required to run your component at that time.
If you have some known set of rust traits that are your cast targets, then you might be able to generate code for the set of worlds that correspond to those targets. You could use bindgen! for that, but you don't have to - bindgen is just a convenience on top of the public wasmtime API, so you can get the same type safety by just using Instance exports and typed_func: wasmtime will check at runtime to make sure the component you load corresponds to those types. So, there are many ways to go about solving this depending on your use case.
EDIT:
So it all boils down to:
ORIGINAL:
Okay, so I am a total noob with
wasm(time)
and my mistake is totally a layer 8 problem. But after digging I couldn't find the solution, so here I am, opening an issue (sorry for that!)What I want:
I want to leverage
cargo component
andwasmtime
to create a simple plugin system experiment.So I created a new (binary) webassembly component via:
cargo component new test-plugin
.And my
src/main.rs
I then generated the binary via
cargo component build --release
and let it run via:As expected. Via the
wasmtime
cli I cannot--invoke
any functions on awasm32-wasi
webassembly module (at least that's what the cli tells me)...So then I created a
simple-host
as a "normal", "native" rust project, compiled viallvm
:Cargo.toml:
main.rs
When I run this I get a
panic
forhello export not found
.What am I doing wrong? I also tried with:
greetings.hello
andgreetings:hello
forget_func
but to no avail.On the other hand, if I create a library component via
cargo component new test-plugin-lib --lib
which creates a default wit file and impl for it:and then load this and call it like so:
it works like a charm.
So I guess my problem boils down to one or two things:
1) How do I get a function in an
interface
programmatically likehello
if the wit file looks like:~2) Maybe it's different when it's a "
binary
" webassembly component in contrast to a lib?~I can answer that one: It's not!
If I add a
helloto
function like to:and implement it like so:
then I can invoke
helloto
just fine :)So it all boils down to: