pub struct Linker<T> {/* private fields */ }Expand description
Structure used to link wasm modules/instances together.
This structure is used to assist in instantiating aModule. ALinkeris a way of performing name resolution to make instantiating a module easierthan specifying positional imports toInstance::new.Linker is aname-based resolver where names are dynamically defined and then used toinstantiate aModule.
An important method isLinker::instantiate which takes a module toinstantiate into the provided store. This method will automatically selectall the right imports for theModule to be instantiated, and willotherwise return an error if an import isn’t satisfied.
§Name Resolution
As mentioned previously,Linker is a form of name resolver. It will beusing the string-based names of imports on a module to attempt to select amatching item to hook up to it. This name resolution has two-levels ofnamespaces, a module level and a name level. Each item is defined within amodule and then has its own name. This basically follows the wasm standardfor modularization.
Names in aLinker cannot be defined twice, but allowing duplicates byshadowing the previous definition can be controlled with theLinker::allow_shadowing method.
§Commands and Reactors
TheLinker type provides conveniences for working with WASI Commands andReactors through theLinker::module method. This will automaticallyhandle instantiation and calling_start and such as appropriatedepending on the inferred type of module.
§Type parameterT
It’s worth pointing out that the type parameterT onLinker<T> doesnot represent thatT is stored within aLinker. Rather theT is usedto ensure that linker-defined functions and stores instantiated into all usethe same matchingT as host state.
§MultipleStores
TheLinker type is designed to be compatible, in some scenarios, withinstantiation in multipleStores. Specifically host-defined functionscreated inLinker withLinker::func_new,Linker::func_wrap, andtheir async versions are compatible to instantiate into anyStore. Thisenables programs which want to instantiate lots of modules to create oneLinker value at program start up and use that continuously for eachStore created over the lifetime of the program.
Note that onceStore-owned items, such asGlobal, are defined withinaLinker then it is no longer compatible with anyStore. At thatpoint only theStore that owns theGlobal can be used to instantiatemodules.
§MultipleEngines
TheLinker type is not compatible with usage between multipleEnginevalues. AnEngine is provided when aLinker is created and onlystores and items which originate from thatEngine can be used with thisLinker. If more than oneEngine is used with aLinker then thatmay cause a panic at runtime, similar to how if aFunc is used with thewrongStore that can also panic at runtime.
Implementations§
Source§impl<T>Linker<T>
impl<T>Linker<T>
Sourcepub fnengine(&self) -> &Engine
Available oncrate featureruntime only.
pub fnengine(&self) -> &Engine
runtime only.Returns theEngine this is connected to.
Sourcepub fnallow_shadowing(&mut self, allow:bool) -> &mut Self
Available oncrate featureruntime only.
pub fnallow_shadowing(&mut self, allow:bool) -> &mut Self
runtime only.Configures whether thisLinker will shadow previous duplicatedefinitions of the same signature.
By default aLinker will disallow duplicate definitions of the samesignature. This method, however, can be used to instead allow duplicatesand have the latest definition take precedence when linking modules.
§Examples
letmutlinker = Linker::<()>::new(&engine);linker.func_wrap("","", || {})?;// by default, duplicates are disallowedassert!(linker.func_wrap("","", || {}).is_err());// but shadowing can be configured to be allowed as welllinker.allow_shadowing(true);linker.func_wrap("","", || {})?;Sourcepub fnallow_unknown_exports(&mut self, allow:bool) -> &mut Self
Available oncrate featureruntime only.
pub fnallow_unknown_exports(&mut self, allow:bool) -> &mut Self
runtime only.Configures whether thisLinker will allow unknown exports fromcommand modules.
By default aLinker will error when unknown exports are encounteredin a command module while usingLinker::module.
This method can be used to allow unknown exports from command modules.
§Examples
letmutlinker = Linker::new(&engine);linker.allow_unknown_exports(true);linker.module(&mutstore,"mod",&module)?;Sourcepub fndefine_unknown_imports_as_traps(&mut self, module: &Module) ->Result<()>where T: 'static,
Available oncrate featureruntime only.
pub fndefine_unknown_imports_as_traps(&mut self, module: &Module) ->Result<()>where T: 'static,
runtime only.Implement any imports of the givenModule with a function which traps.
By default aLinker will error when unknown imports are encounteredin a command module while usingLinker::module.
This method can be used to allow unknown imports from command modules.
§Examples
letmutlinker = Linker::new(&engine);linker.define_unknown_imports_as_traps(&module)?;linker.instantiate(&mutstore,&module)?;Sourcepub fndefine_unknown_imports_as_default_values( &mut self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<()>where T: 'static,
Available oncrate featureruntime only.
pub fndefine_unknown_imports_as_default_values( &mut self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<()>where T: 'static,
runtime only.Implement any function imports of theModule with a function thatignores its arguments and returns default values.
Default values are either zero or null, depending on the value type.
This method can be used to allow unknown imports from command modules.
§Example
letmutlinker = Linker::new(&engine);linker.define_unknown_imports_as_default_values(&mutstore,&module)?;linker.instantiate(&mutstore,&module)?;Sourcepub fndefine( &mut self, store: implAsContext<Data = T>, module: &str, name: &str, item: implInto<Extern>,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fndefine( &mut self, store: implAsContext<Data = T>, module: &str, name: &str, item: implInto<Extern>,) ->Result<&mut Self>where T: 'static,
runtime only.Defines a new item in thisLinker.
This method will add a new definition, by name, to this instance ofLinker. Themodule andname provided are what to name theitem.
§Errors
Returns an error if themodule andname already identify an itemof the same type as theitem provided and if shadowing is disallowed.For more information see the documentation onLinker.
§Examples
letmutlinker = Linker::new(&engine);letty = GlobalType::new(ValType::I32, Mutability::Const);letglobal = Global::new(&mutstore, ty, Val::I32(0x1234))?;linker.define(&store,"host","offset", global)?;letwat =r#" (module (import "host" "offset" (global i32)) (memory 1) (data (global.get 0) "foo") )"#;letmodule = Module::new(&engine, wat)?;linker.instantiate(&mutstore,&module)?;Sourcepub fndefine_name( &mut self, store: implAsContext<Data = T>, name: &str, item: implInto<Extern>,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fndefine_name( &mut self, store: implAsContext<Data = T>, name: &str, item: implInto<Extern>,) ->Result<&mut Self>where T: 'static,
runtime only.Same asLinker::define, except only the name of the import isprovided, not a module name as well.
This is only relevant when working with the module linking proposalwhere one-level names are allowed (in addition to two-level names).Otherwise this method need not be used.
Sourcepub fnfunc_new( &mut self, module: &str, name: &str, ty:FuncType, func: implFn(Caller<'_, T>, &[Val], &mut [Val]) ->Result<()> +Send +Sync + 'static,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fnfunc_new( &mut self, module: &str, name: &str, ty:FuncType, func: implFn(Caller<'_, T>, &[Val], &mut [Val]) ->Result<()> +Send +Sync + 'static,) ->Result<&mut Self>where T: 'static,
runtime only.Creates aFunc::new-style function named in this linker.
For more information seeLinker::func_wrap.
§Panics
Panics if the given function type is not associated with the same engineas this linker.
Sourcepub unsafe fnfunc_new_unchecked( &mut self, module: &str, name: &str, ty:FuncType, func: implFn(Caller<'_, T>, &mut [MaybeUninit<ValRaw>]) ->Result<()> +Send +Sync + 'static,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub unsafe fnfunc_new_unchecked( &mut self, module: &str, name: &str, ty:FuncType, func: implFn(Caller<'_, T>, &mut [MaybeUninit<ValRaw>]) ->Result<()> +Send +Sync + 'static,) ->Result<&mut Self>where T: 'static,
runtime only.Creates aFunc::new_unchecked-style function named in this linker.
For more information seeLinker::func_wrap.
§Panics
Panics if the given function type is not associated with the same engineas this linker.
§Safety
SeeFunc::new_unchecked for more safety information.
Sourcepub fnfunc_new_async<F>( &mut self, module: &str, name: &str, ty:FuncType, func: F,) ->Result<&mut Self>
Available oncrate featuresruntime andasync only.
pub fnfunc_new_async<F>( &mut self, module: &str, name: &str, ty:FuncType, func: F,) ->Result<&mut Self>
runtime andasync only.Creates aFunc::new_async-style function named in this linker.
For more information seeLinker::func_wrap.
§Panics
This method panics in the following situations:
- If the given function type is not associated with the same engine asthis linker.
Sourcepub fnfunc_wrap<Params, Args>( &mut self, module: &str, name: &str, func: implIntoFunc<T, Params, Args>,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fnfunc_wrap<Params, Args>( &mut self, module: &str, name: &str, func: implIntoFunc<T, Params, Args>,) ->Result<&mut Self>where T: 'static,
runtime only.Define a host function within this linker.
For information about how the host function operates, seeFunc::wrap. That includes information about translating Rust typesto WebAssembly native types.
This method creates a host-provided function in this linker under theprovided name. This method is distinct in its capability to create aStore-independent function. This means that thefunction defined here can be used to instantiate instances in multipledifferent stores, or in other words the function can be loaded intodifferent stores.
Note that the capability mentioned here applies to all otherhost-function-defining-methods onLinker as well. All of them can beused to create instances ofFunc within multiple stores. In amultithreaded program, for example, this means that the host functionscould be called concurrently if different stores are executing ondifferent threads.
§Errors
Returns an error if themodule andname already identify an itemof the same type as theitem provided and if shadowing is disallowed.For more information see the documentation onLinker.
§Examples
letmutlinker = Linker::new(&engine);linker.func_wrap("host","double", |x: i32| x *2)?;linker.func_wrap("host","log_i32", |x: i32|println!("{}", x))?;linker.func_wrap("host","log_str", |caller: Caller<'_, ()>, ptr: i32, len: i32| {// ...})?;letwat =r#" (module (import "host" "double" (func (param i32) (result i32))) (import "host" "log_i32" (func (param i32))) (import "host" "log_str" (func (param i32 i32))) )"#;letmodule = Module::new(&engine, wat)?;// instantiate in multiple different storesfor _ in0..10{letmutstore = Store::new(&engine, ()); linker.instantiate(&mutstore,&module)?;}Sourcepub fnfunc_wrap_async<F, Params:WasmTyList, Args:WasmRet>( &mut self, module: &str, name: &str, func: F,) ->Result<&mut Self>
Available oncrate featuresruntime andasync only.
pub fnfunc_wrap_async<F, Params:WasmTyList, Args:WasmRet>( &mut self, module: &str, name: &str, func: F,) ->Result<&mut Self>
runtime andasync only.Asynchronous analog ofLinker::func_wrap.
Sourcepub fninstance( &mut self, store: implAsContextMut<Data = T>, module_name: &str, instance:Instance,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fninstance( &mut self, store: implAsContextMut<Data = T>, module_name: &str, instance:Instance,) ->Result<&mut Self>where T: 'static,
runtime only.Convenience wrapper to define an entireInstance in this linker.
This function is a convenience wrapper aroundLinker::define whichwill define all exports oninstance into this linker. The module namefor each export ismodule_name, and the name for each export is thename in the instance itself.
Note that when this API is used theLinker is no longer compatiblewith multi-Store instantiation because the itemsdefined within this store will belong to thestore provided, and onlythestore provided.
§Errors
Returns an error if the any item is redefined twice in this linker (forexample the samemodule_name was already defined) and shadowing isdisallowed, or ifinstance comes from a differentStore than thisLinker originally was createdwith.
§Panics
Panics ifinstance does not belong tostore.
§Examples
letmutlinker = Linker::new(&engine);// Instantiate a small instance...letwat =r#"(module (func (export "run") ))"#;letmodule = Module::new(&engine, wat)?;letinstance = linker.instantiate(&mutstore,&module)?;// ... and inform the linker that the name of this instance is// `instance1`. This defines the `instance1::run` name for our next// module to use.linker.instance(&mutstore,"instance1", instance)?;letwat =r#" (module (import "instance1" "run" (func $instance1_run)) (func (export "run") call $instance1_run ) )"#;letmodule = Module::new(&engine, wat)?;letinstance = linker.instantiate(&mutstore,&module)?;Sourcepub fnmodule( &mut self, store: implAsContextMut<Data = T>, module_name: &str, module: &Module,) ->Result<&mut Self>where T: 'static,
Available oncrate featureruntime only.
pub fnmodule( &mut self, store: implAsContextMut<Data = T>, module_name: &str, module: &Module,) ->Result<&mut Self>where T: 'static,
runtime only.Define automatic instantiations of aModule in this linker.
This automatically handlesCommands and Reactors instantiation andinitialization.
Exported functions of a Command module may be called directly, howeverinstead of having a single instance which is reused for each call,each call creates a new instance, which lives for the duration of thecall. The imports of the Command are resolved once, and reused foreach instantiation, so all dependencies need to be present at the timewhenLinker::module is called.
For Reactors, a single instance is created, and an initializationfunction is called, and then its exports may be called.
Ordinary modules which don’t declare themselves to be either Commandsor Reactors are treated as Reactors without any initialization calls.
§Errors
Returns an error if the any item is redefined twice in this linker (forexample the samemodule_name was already defined) and shadowing isdisallowed, ifinstance comes from a differentStore than thisLinker originally was createdwith, or if a Reactor initialization function traps.
§Panics
Panics if any item used to instantiate the providedModule is notowned bystore, or if thestore provided comes from a differentEngine than thisLinker.
§Examples
letmutlinker = Linker::new(&engine);// Instantiate a small instance and inform the linker that the name of// this instance is `instance1`. This defines the `instance1::run` name// for our next module to use.letwat =r#"(module (func (export "run") ))"#;letmodule = Module::new(&engine, wat)?;linker.module(&mutstore,"instance1",&module)?;letwat =r#" (module (import "instance1" "run" (func $instance1_run)) (func (export "run") call $instance1_run ) )"#;letmodule = Module::new(&engine, wat)?;letinstance = linker.instantiate(&mutstore,&module)?;For a Command, a new instance is created for each call.
letmutlinker = Linker::new(&engine);// Create a Command that attempts to count the number of times it is run, but is// foiled by each call getting a new instance.letwat =r#" (module (global $counter (mut i32) (i32.const 0)) (func (export "_start") (global.set $counter (i32.add (global.get $counter) (i32.const 1))) ) (func (export "read_counter") (result i32) (global.get $counter) ) )"#;letmodule = Module::new(&engine, wat)?;linker.module(&mutstore,"commander",&module)?;letrun = linker.get_default(&mutstore,"")?.typed::<(), ()>(&store)?.clone();run.call(&mutstore, ())?;run.call(&mutstore, ())?;run.call(&mutstore, ())?;letwat =r#" (module (import "commander" "_start" (func $commander_start)) (import "commander" "read_counter" (func $commander_read_counter (result i32))) (func (export "run") (result i32) call $commander_start call $commander_start call $commander_start call $commander_read_counter ) )"#;letmodule = Module::new(&engine, wat)?;linker.module(&mutstore,"",&module)?;letrun = linker.get(&mutstore,"","run").unwrap().into_func().unwrap();letcount = run.typed::<(), i32>(&store)?.call(&mutstore, ())?;assert_eq!(count,0,"a Command should get a fresh instance on each invocation");Sourcepub async fnmodule_async( &mut self, store: implAsContextMut<Data = T>, module_name: &str, module: &Module,) ->Result<&mut Self>where T:Send + 'static,
Available oncrate featuresruntime andasync only.
pub async fnmodule_async( &mut self, store: implAsContextMut<Data = T>, module_name: &str, module: &Module,) ->Result<&mut Self>where T:Send + 'static,
runtime andasync only.Define automatic instantiations of aModule in this linker.
This is the same asLinker::module, except for asyncStores.
Sourcepub fnalias( &mut self, module: &str, name: &str, as_module: &str, as_name: &str,) ->Result<&mut Self>
Available oncrate featureruntime only.
pub fnalias( &mut self, module: &str, name: &str, as_module: &str, as_name: &str,) ->Result<&mut Self>
runtime only.Aliases one item’s name as another.
This method will alias an item with the specifiedmodule andnameunder a new name ofas_module andas_name.
§Errors
Returns an error if any shadowing violations happen while defining newitems, or if the original item wasn’t defined.
Sourcepub fnalias_module(&mut self, module: &str, as_module: &str) ->Result<()>
Available oncrate featureruntime only.
pub fnalias_module(&mut self, module: &str, as_module: &str) ->Result<()>
runtime only.Aliases one module’s name as another.
This method will alias all currently defined undermodule to also bedefined under the nameas_module too.
§Errors
Returns an error if any shadowing violations happen while defining newitems.
Sourcepub fninstantiate( &self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<Instance>where T: 'static,
Available oncrate featureruntime only.
pub fninstantiate( &self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<Instance>where T: 'static,
runtime only.Attempts to instantiate themodule provided.
This method will attempt to assemble a list of imports that correspondto the imports required by theModule provided. This listof imports is then passed toInstance::new to continue theinstantiation process.
Each import ofmodule will be looked up in thisLinker and musthave previously been defined. If it was previously defined with anincorrect signature or if it was not previously defined then an errorwill be returned because the import can not be satisfied.
Per the WebAssembly spec, instantiation includes running the module’sstart function, if it has one (not to be confused with the_startfunction, which is not run).
§Errors
This method can fail because an import may not be found, or becauseinstantiation itself may fail. For information on instantiationfailures seeInstance::new. If an import is not found, the errormay be downcast to anUnknownImportError.
§Panics
Panics if any item used to instantiatemodule is not owned bystore. Additionally this will panic if theEngine that thestorebelongs to is different than thisLinker.
§Examples
letmutlinker = Linker::new(&engine);linker.func_wrap("host","double", |x: i32| x *2)?;letwat =r#" (module (import "host" "double" (func (param i32) (result i32))) )"#;letmodule = Module::new(&engine, wat)?;linker.instantiate(&mutstore,&module)?;Sourcepub async fninstantiate_async( &self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<Instance>where T:Send + 'static,
Available oncrate featuresruntime andasync only.
pub async fninstantiate_async( &self, store: implAsContextMut<Data = T>, module: &Module,) ->Result<Instance>where T:Send + 'static,
runtime andasync only.Attempts to instantiate themodule provided. This is the same asLinker::instantiate, except for asyncStores.
Sourcepub fninstantiate_pre(&self, module: &Module) ->Result<InstancePre<T>>where T: 'static,
Available oncrate featureruntime only.
pub fninstantiate_pre(&self, module: &Module) ->Result<InstancePre<T>>where T: 'static,
runtime only.Performs all checks necessary for instantiatingmodule with thislinker, except that instantiation doesn’t actually finish.
This method is used for front-loading type-checking information as wellas collecting the imports to use to instantiate a module with. ThereturnedInstancePre represents a ready-to-be-instantiated module,which can also be instantiated multiple times if desired.
§Errors
Returns an error which may be downcast to anUnknownImportError ifthe module has any unresolvable imports.
§Examples
letmutlinker = Linker::new(&engine);linker.func_wrap("host","double", |x: i32| x *2)?;letwat =r#" (module (import "host" "double" (func (param i32) (result i32))) )"#;letmodule = Module::new(&engine, wat)?;letinstance_pre = linker.instantiate_pre(&module)?;// Finish instantiation after the type-checking has all completed...letinstance = instance_pre.instantiate(&mutstore)?;// ... and we can even continue to keep instantiating if desired!instance_pre.instantiate(&mutstore)?;instance_pre.instantiate(&mutstore)?;// Note that functions defined in a linker with `func_wrap` and similar// constructors are not owned by any particular `Store`, so we can also// instantiate our `instance_pre` in other stores because no imports// belong to the original store.letmutnew_store = Store::new(&engine, ());instance_pre.instantiate(&mutnew_store)?;Sourcepub fniter<'a: 'p, 'p>( &'a self, store: implAsContextMut<Data = T> + 'p,) -> implIterator<Item = (&'astr, &'astr,Extern)> + 'pwhere T: 'static,
Available oncrate featureruntime only.
pub fniter<'a: 'p, 'p>( &'a self, store: implAsContextMut<Data = T> + 'p,) -> implIterator<Item = (&'astr, &'astr,Extern)> + 'pwhere T: 'static,
runtime only.Returns an iterator over all items defined in thisLinker, inarbitrary order.
The iterator returned will yield 3-tuples where the first two elementsare the module name and item name for the external item, and the thirditem is the item itself that is defined.
Note that multipleExtern items may be defined for the samemodule/name pair.
§Panics
This function will panic if thestore provided does not come from thesameEngine that this linker was created with.
Sourcepub fnget( &self, store: implAsContextMut<Data = T>, module: &str, name: &str,) ->Option<Extern>where T: 'static,
Available oncrate featureruntime only.
pub fnget( &self, store: implAsContextMut<Data = T>, module: &str, name: &str,) ->Option<Extern>where T: 'static,
runtime only.Sourcepub fnget_by_import( &self, store: implAsContextMut<Data = T>, import: &ImportType<'_>,) ->Option<Extern>where T: 'static,
Available oncrate featureruntime only.
pub fnget_by_import( &self, store: implAsContextMut<Data = T>, import: &ImportType<'_>,) ->Option<Extern>where T: 'static,
runtime only.Sourcepub fnget_default( &self, store: implAsContextMut<Data = T>, module: &str,) ->Result<Func>where T: 'static,
Available oncrate featureruntime only.
pub fnget_default( &self, store: implAsContextMut<Data = T>, module: &str,) ->Result<Func>where T: 'static,
runtime only.Returns the “default export” of a module.
An export with an empty string is considered to be a “default export”.“_start” is also recognized for compatibility.
§Panics
Panics if the default function found is not owned bystore. Thisfunction will also panic if thestore provided does not come from thesameEngine that this linker was created with.
Trait Implementations§
Auto Trait Implementations§
impl<T>Freeze forLinker<T>
impl<T> !RefUnwindSafe forLinker<T>
impl<T>Send forLinker<T>
impl<T>Sync forLinker<T>
impl<T>Unpin forLinker<T>
impl<T> !UnwindSafe forLinker<T>
Blanket Implementations§
Source§impl<T>BorrowMut<T> for Twhere T: ?Sized,
impl<T>BorrowMut<T> for Twhere T: ?Sized,
Source§fnborrow_mut(&mut self) ->&mut T
fnborrow_mut(&mut self) ->&mut T
Source§impl<T>CloneToUninit for Twhere T:Clone,
impl<T>CloneToUninit for Twhere T:Clone,
Source§impl<T>IntoEither for T
impl<T>IntoEither for T
Source§fninto_either(self, into_left:bool) ->Either<Self, Self>ⓘ
fninto_either(self, into_left:bool) ->Either<Self, Self>ⓘ
self into aLeft variant ofEither<Self, Self>ifinto_left istrue.Convertsself into aRight variant ofEither<Self, Self>otherwise.Read moreSource§fninto_either_with<F>(self, into_left: F) ->Either<Self, Self>ⓘ
fninto_either_with<F>(self, into_left: F) ->Either<Self, Self>ⓘ
self into aLeft variant ofEither<Self, Self>ifinto_left(&self) returnstrue.Convertsself into aRight variant ofEither<Self, Self>otherwise.Read more