pub struct Linker<T> { }
Available on crate feature runtime
only.
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.
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.
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.
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.
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 within 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.
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.
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 Engine
s may cause a panic when used with this Linker
.
Returns the Engine
this is connected to.
Configures whether this Linker
will shadow previous duplicate definitions of the same signature.
By default a Linker
will disallow duplicate definitions of the same signature. This method, however, can be used to instead allow duplicates and have the latest definition take precedence when linking modules.
let mut linker = Linker::<()>::new(&engine);
linker.func_wrap("", "", || {})?;
assert!(linker.func_wrap("", "", || {}).is_err());
linker.allow_shadowing(true);
linker.func_wrap("", "", || {})?;
Source
Configures whether this Linker
will allow unknown exports from command modules.
By default a Linker
will error when unknown exports are encountered in a command module while using Linker::module
.
This method can be used to allow unknown exports from command modules.
§Exampleslet mut linker = Linker::new(&engine);
linker.allow_unknown_exports(true);
linker.module(&mut store, "mod", &module)?;
Source
Implement any imports of the given Module
with a function which traps.
By default a Linker
will error when unknown imports are encountered in a command module while using Linker::module
.
This method can be used to allow unknown imports from command modules.
§Exampleslet mut linker = Linker::new(&engine);
linker.define_unknown_imports_as_traps(&module)?;
linker.instantiate(&mut store, &module)?;
Source
Implement any function imports of the Module
with a function that ignores 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.
§Examplelet mut linker = Linker::new(&engine);
linker.define_unknown_imports_as_default_values(&mut store, &module)?;
linker.instantiate(&mut store, &module)?;
Source
Defines a new item in this Linker
.
This method will add a new definition, by name, to this instance of Linker
. The module
and name
provided are what to name the item
.
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
.
let mut linker = Linker::new(&engine);
let ty = GlobalType::new(ValType::I32, Mutability::Const);
let global = Global::new(&mut store, ty, Val::I32(0x1234))?;
linker.define(&store, "host", "offset", global)?;
let wat = r#"
(module
(import "host" "offset" (global i32))
(memory 1)
(data (global.get 0) "foo")
)
"#;
let module = Module::new(&engine, wat)?;
linker.instantiate(&mut store, &module)?;
Source
Same as Linker::define
, except only the name of the import is provided, not a module name as well.
This is only relevant when working with the module linking proposal where one-level names are allowed (in addition to two-level names). Otherwise this method need not be used.
SourceCreates a Func::new
-style function named in this linker.
For more information see Linker::func_wrap
.
Panics if the given function type is not associated with the same engine as this linker.
Source SourceAvailable on crate features async
and cranelift
only.
Creates a Func::new_async
-style function named in this linker.
For more information see Linker::func_wrap
.
This method panics in the following situations:
This linker is not associated with an async config.
If the given function type is not associated with the same engine as this linker.
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.
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
.
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)?;
for _ in 0..10 {
let mut store = Store::new(&engine, ());
linker.instantiate(&mut store, &module)?;
}
Source
Available on crate feature async
only.
Asynchronous analog of Linker::func_wrap
.
Convenience wrapper to define an entire Instance
in this linker.
This function is a convenience wrapper around Linker::define
which will define all exports on instance
into this linker. The module name for each export is module_name
, and the name for each export is the name in the instance itself.
Note that when this API is used the Linker
is no longer compatible with multi-Store
instantiation because the items defined within this store will belong to the store
provided, and only the store
provided.
Returns an error if the any item is redefined twice in this linker (for example the same module_name
was already defined) and shadowing is disallowed, or if instance
comes from a different Store
than this Linker
originally was created with.
Panics if instance
does not belong to store
.
let mut linker = Linker::new(&engine);
let wat = r#"(module (func (export "run") ))"#;
let module = Module::new(&engine, wat)?;
let instance = linker.instantiate(&mut store, &module)?;
linker.instance(&mut store, "instance1", instance)?;
let wat = r#"
(module
(import "instance1" "run" (func $instance1_run))
(func (export "run")
call $instance1_run
)
)
"#;
let module = Module::new(&engine, wat)?;
let instance = linker.instantiate(&mut store, &module)?;
Source
Define automatic instantiations of a Module
in this linker.
This automatically handles Commands and Reactors instantiation and initialization.
Exported functions of a Command module may be called directly, however instead of having a single instance which is reused for each call, each call creates a new instance, which lives for the duration of the call. The imports of the Command are resolved once, and reused for each instantiation, so all dependencies need to be present at the time when Linker::module
is called.
For Reactors, a single instance is created, and an initialization function is called, and then its exports may be called.
Ordinary modules which don’t declare themselves to be either Commands or Reactors are treated as Reactors without any initialization calls.
§ErrorsReturns an error if the any item is redefined twice in this linker (for example the same module_name
was already defined) and shadowing is disallowed, if instance
comes from a different Store
than this Linker
originally was created with, or if a Reactor initialization function traps.
Panics if any item used to instantiate the provided Module
is not owned by store
, or if the store
provided comes from a different Engine
than this Linker
.
let mut linker = Linker::new(&engine);
let wat = r#"(module (func (export "run") ))"#;
let module = Module::new(&engine, wat)?;
linker.module(&mut store, "instance1", &module)?;
let wat = r#"
(module
(import "instance1" "run" (func $instance1_run))
(func (export "run")
call $instance1_run
)
)
"#;
let module = Module::new(&engine, wat)?;
let instance = linker.instantiate(&mut store, &module)?;
For a Command, a new instance is created for each call.
let mut linker = Linker::new(&engine);
let wat = 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)
)
)
"#;
let module = Module::new(&engine, wat)?;
linker.module(&mut store, "commander", &module)?;
let run = linker.get_default(&mut store, "")?
.typed::<(), ()>(&store)?
.clone();
run.call(&mut store, ())?;
run.call(&mut store, ())?;
run.call(&mut store, ())?;
let wat = 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
)
)
"#;
let module = Module::new(&engine, wat)?;
linker.module(&mut store, "", &module)?;
let run = linker.get(&mut store, "", "run").unwrap().into_func().unwrap();
let count = run.typed::<(), i32>(&store)?.call(&mut store, ())?;
assert_eq!(count, 0, "a Command should get a fresh instance on each invocation");
Source
Available on crate features async
and cranelift
only.
Define automatic instantiations of a Module
in this linker.
This is the same as Linker::module
, except for async Store
s.
Aliases one item’s name as another.
This method will alias an item with the specified module
and name
under a new name of as_module
and as_name
.
Returns an error if any shadowing violations happen while defining new items, or if the original item wasn’t defined.
SourceAliases one module’s name as another.
This method will alias all currently defined under module
to also be defined under the name as_module
too.
Returns an error if any shadowing violations happen while defining new items.
SourceAttempts 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).
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 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
.
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
Available on crate feature async
only.
Attempts to instantiate the module
provided. This is the same as Linker::instantiate
, except for async Store
s.
Performs all checks necessary for instantiating module
with this linker, except that instantiation doesn’t actually finish.
This method is used for front-loading type-checking information as well as collecting the imports to use to instantiate a module with. The returned InstancePre
represents a ready-to-be-instantiated module, which can also be instantiated multiple times if desired.
Returns an error which may be downcast to an UnknownImportError
if the module has any unresolvable imports.
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)?;
let instance_pre = linker.instantiate_pre(&module)?;
let instance = instance_pre.instantiate(&mut store)?;
instance_pre.instantiate(&mut store)?;
instance_pre.instantiate(&mut store)?;
let mut new_store = Store::new(&engine, ());
instance_pre.instantiate(&mut new_store)?;
Source
Returns an iterator over all items defined in this Linker
, in arbitrary order.
The iterator returned will yield 3-tuples where the first two elements are the module name and item name for the external item, and the third item is the item itself that is defined.
Note that multiple Extern
items may be defined for the same module/name pair.
This function will panic if the store
provided does not come from the same Engine
that this linker was created with.
Looks up a previously defined value in this Linker
, identified by the names provided.
Returns None
if this name was not previously defined in this Linker
.
This function will panic if the store
provided does not come from the same Engine
that this linker was created with.
Looks up a value in this Linker
which matches the import
type provided.
Returns None
if no match was found.
This function will panic if the store
provided does not come from the same Engine
that this linker was created with.
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.
§PanicsPanics if the default function found is not owned by store
. This function will also panic if the store
provided does not come from the same Engine
that this linker was created with.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4