Struct wasm_bridge::Linker
source · pub struct Linker<T>(/* private fields */);
Expand description
Structure used to link wasm modules/instances together.
This structure is used to assist in instantiating a Module
. A Linker
is a way of performing name resolution to make instantiating a module easier
than specifying positional imports to Instance::new
. Linker
is a
name-based resolver where names are dynamically defined and then used to
instantiate a Module
.
An important method is Linker::instantiate
which takes a module to
instantiate into the provided store. This method will automatically select
all the right imports for the Module
to be instantiated, and will
otherwise return an error if an import isn’t satisfied.
§Name Resolution
As mentioned previously, Linker
is a form of name resolver. It will be
using the string-based names of imports on a module to attempt to select a
matching item to hook up to it. This name resolution has two-levels of
namespaces, a module level and a name level. Each item is defined within a
module and then has its own name. This basically follows the wasm standard
for modularization.
Names in a Linker
cannot be defined twice, but allowing duplicates by
shadowing the previous definition can be controlled with the
[Linker::allow_shadowing
] method.
§Commands and Reactors
The Linker
type provides conveniences for working with WASI Commands and
Reactors through the [Linker::module
] method. This will automatically
handle instantiation and calling _start
and such as appropriate
depending on the inferred type of module.
§Type parameter T
It’s worth pointing out that the type parameter T
on Linker<T>
does
not represent that T
is stored within a Linker
. Rather the T
is used
to ensure that linker-defined functions and stores instantiated into all use
the same matching T
as host state.
§Multiple Store
s
The Linker
type is designed to be compatible, in some scenarios, with
instantiation in multiple Store
s. Specifically host-defined functions
created in Linker
with Linker::func_new
, Linker::func_wrap
, and
their async versions are compatible to instantiate into any Store
. This
enables programs which want to instantiate lots of modules to create one
Linker
value at program start up and use that continuously for each
Store
created over the lifetime of the program.
Note that once Store
-owned items, such as Global
, are defined witin
a Linker
then it is no longer compatible with any Store
. At that
point only the Store
that owns the Global
can be used to instantiate
modules.
§Multiple Engine
s
The Linker
type is not compatible with usage between multiple Engine
values. An Engine
is provided when a Linker
is created and only
stores and items which originate from that Engine
can be used with this
Linker
. If more than one Engine
is used with a Linker
then that
may cause a panic at runtime, similar to how if a Func
is used with the
wrong Store
that can also panic at runtime.
Implementations§
source§impl<T> Linker<T>
impl<T> Linker<T>
pub fn instantiate( &self, store: impl AsContextMut<Data = T>, module: &Module ) -> Result<Instance, Error>
instantiate_safe
instead.sourcepub async fn instantiate_safe(
&self,
store: impl AsContextMut<Data = T>,
module: &Module
) -> Result<Instance, Error>
pub async fn instantiate_safe( &self, store: impl AsContextMut<Data = T>, module: &Module ) -> Result<Instance, Error>
Attempts to instantiate the module
provided.
This method will attempt to assemble a list of imports that correspond
to the imports required by the Module
provided. This list
of imports is then passed to Instance::new
to continue the
instantiation process.
Each import of module
will be looked up in this Linker
and must
have previously been defined. If it was previously defined with an
incorrect signature or if it was not previously defined then an error
will be returned because the import can not be satisfied.
Per the WebAssembly spec, instantiation includes running the module’s
start function, if it has one (not to be confused with the _start
function, which is not run).
§Errors
This method can fail because an import may not be found, or because
instantiation itself may fail. For information on instantiation
failures see Instance::new
. If an import is not found, the error
may be downcast to an UnknownImportError
.
§Panics
Panics if any item used to instantiate module
is not owned by
store
. Additionally this will panic if the Engine
that the store
belongs to is different than this Linker
.
§Examples
let mut linker = Linker::new(&engine);
linker.func_wrap("host", "double", |x: i32| x * 2)?;
let wat = r#"
(module
(import "host" "double" (func (param i32) (result i32)))
)
"#;
let module = Module::new(&engine, wat)?;
linker.instantiate(&mut store, &module)?;
sourcepub fn func_new(
&mut self,
module: &str,
name: &str,
ty: FuncType,
func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static
) -> Result<&mut Self>
pub fn func_new( &mut self, module: &str, name: &str, ty: FuncType, func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static ) -> Result<&mut Self>
Creates a Func::new
-style function named in this linker.
For more information see Linker::func_wrap
.
§Panics
Panics if the given function type is not associated with the same engine as this linker.
sourcepub fn func_wrap<Params, Results>(
&mut self,
module: &str,
name: &str,
func: impl IntoFunc<T, Params, Results>
) -> Result<&mut Self>
pub fn func_wrap<Params, Results>( &mut self, module: &str, name: &str, func: impl IntoFunc<T, Params, Results> ) -> Result<&mut Self>
Define a host function within this linker.
For information about how the host function operates, see
Func::wrap
. That includes information about translating Rust types
to WebAssembly native types.
This method creates a host-provided function in this linker under the
provided name. This method is distinct in its capability to create a
Store
-independent function. This means that the
function defined here can be used to instantiate instances in multiple
different stores, or in other words the function can be loaded into
different stores.
Note that the capability mentioned here applies to all other
host-function-defining-methods on Linker
as well. All of them can be
used to create instances of Func
within multiple stores. In a
multithreaded program, for example, this means that the host functions
could be called concurrently if different stores are executing on
different threads.
§Errors
Returns an error if the module
and name
already identify an item
of the same type as the item
provided and if shadowing is disallowed.
For more information see the documentation on Linker
.
§Examples
let mut linker = 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| {
// ...
})?;
let wat = 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)))
)
"#;
let module = Module::new(&engine, wat)?;
// instantiate in multiple different stores
for _ in 0..10 {
let mut store = Store::new(&engine, ());
linker.instantiate(&mut store, &module)?;
}
Trait Implementations§
Auto Trait Implementations§
impl<T> Freeze for Linker<T>
impl<T> !RefUnwindSafe for Linker<T>
impl<T> Send for Linker<T>
impl<T> Sync for Linker<T>
impl<T> Unpin for Linker<T>
impl<T> !UnwindSafe for Linker<T>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more