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 Stores

The Linker type is designed to be compatible, in some scenarios, with instantiation in multiple Stores. 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 Engines

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>

source

pub fn new(engine: &Engine) -> Self

Creates a new Linker.

The linker will define functions within the context of the engine provided and can only instantiate modules for a Store that is also defined within the same Engine. Usage of stores with different Engines may cause a panic when used with this Linker.

source

pub fn instantiate( &self, store: impl AsContextMut<Data = T>, module: &Module ) -> Result<Instance, Error>

👎Deprecated since 0.4.0: Instantiating a module synchronously can panic on the web, please use instantiate_safe instead.
source

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)?;
source

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.

source

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§

source§

impl<T: Clone> Clone for Linker<T>

source§

fn clone(&self) -> Linker<T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T> RefCast for Linker<T>

§

type From = Linker<T>

source§

fn ref_cast(_from: &Self::From) -> &Self

source§

fn ref_cast_mut(_from: &mut Self::From) -> &mut Self

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> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.