Open bobogei81123 opened 1 year ago
You mention that a single linker is used for a store, but that's not quite accurate because you can use any number of linkers to instantiate within a Store
. In that sense you can still provide per-function state within the Linker
. Otherwise though I'll also note that the question there was in reference to the C API and the Rust API is a bit different. In Rust the closures in Linker
are Fn
meaning you don't get mutable access to closed-over-state. Instead that sort of information typically goes within the T
of a Store<T>
which you do get mutable access to.
So, if possible, the recommendation is to store per-instance information into a T
in Store<T>
and only if necessary store per-instance information within the closures passed to a Linker
. Does that work for you?
I'll also note that the question there was in reference to the C API and the Rust API is a bit different.
Sorry for not stating the question clearly. I'm using the rust API. Otherwise
So, if possible, the recommendation is to store per-instance information into a T in Store
and only if necessary store per-instance information within the closures passed to a Linker. Does that work for you?
I'm a little bit confused here because I thought there can be multiple instances inside a single store. My setup is as follows:
First I create a global Engine
and Store
:
fn init() {
engine = Engine::new(config)?;
store = Store::new(...);
linker = Linker::new(&engine);
MyWasmWorld::add_to_linker(&mut linker, ...)?;
...
}
Then, when a plugin (guest program) is loaded, I load the wasm file and instantiate the component
fn load_plugin_from_path(file_path: &str) {
Component::from_file(engine, file_path)?;
let (_, instance) = MyWasmWorld::instantiate(&mut store, &component, &linker)?;
...
}
My understanding is that load_plugin_from_path
can be called multiple time to instantiate multiple plugins in the same store, so I'll need a way to identify which instance is calling the host function.
Or should I use multiple stores for different plugins? But even then, I still need to get the Instance
handle to get its exports so I cn call guest functions or inspect its memory, is that correct?
Oh, I think I get what you are suggesting, I can create one linker each time I instantiate a plugin. Let me try if that works.
Ah yes it's possible to put lots of instances in the same store. The downside of that approach is that you can't incrementally delete instances within the store, it's an all-or-nothing operation (e.g. you can't unload just one plugin, you'd have to unload all of them).
If possible I'd recommend having a Store
-per-plugin. With the component abstraction it's not actually necessary to have everything in one store as that's primarily there for core wasm instance linking and shared memory, which the component model doesn't support.
Storing state per-linker would still work, however, if that works for you!
@alexcrichton, not sure if this is the best place to ask the question, but is there a clean way to call guest functions from without a host function? (I'm not currently using the component model, if that makes a difference).
I have a bunch of host functions that allocate their results. To do so, they rely on an allocate
function exported from the wasm-module. I know I can dynamically get the export and do all the checking, but is there a way to do this at link-time?
It would be nice if there was a way for Linker::instantiate
to check for exports in addition to imports in a way that would enable me to make safe static calls back into the module.
Or maybe I just want to expose Instance::get_module_export
off of Caller
so I don't have to do a lookup by name every time and put the ModuleExport
in the Store
-data?
Should I be thinking about allocation differently? Is there another way to do this? Please advise if there's a better place to post too.
I'll follow up on https://github.com/bytecodealliance/wasmtime/pull/9525 as this probably isn't the best place to continue this discussion (but no worries!)
Feature
Provide instance (
Instance
struct) or instance data to host defined functions in component model.Benefit
In #2491, it is suggested to bind the instance data to the closure passed to
Func::wrap
to store per-instance data. However, this will not work for instances in component model because to bind a function (let host export a function to be called by guests), one need to configureLinkerInstance
(e.g., useLinkerInstance::func_wrap
or similar methods). Yet, there is only a single linker set up for instantiating all the instances in a store, so there is no way to configure per-instance data.Providing host function instance and instance data will let host function able to get data tied to the instance that calls the function, or let host perform a nested call to a guest function, etc.
Implementation
I think a possible implementation is to let the function passed to
LinkerInstance::func_wrap
to be able to takeCaller
instead ofStoreContextMut
. The non-component model counterpartFunc::wrap
takesAsContextMut
to achieve this, and I'm not sure whyfunc_wrap
takesStoreContextMut
instead. Then, we can expose the instance stored in theCaller
struct. Of course, this all rely on the assumption thatCaller
can be retrieve in calls to component host.