Struct wiggle::wasmtime_crate::Func [−][src]
#[repr(transparent)]pub struct Func(_);Expand description
A WebAssembly function which can be called.
This type can represent either an exported function from a WebAssembly
module or a host-defined function which can be used to satisfy an import of
a module. Func and can be used to both instantiate an Instance as
well as be extracted from an Instance.
A Func “belongs” to the store that it was originally created within.
Operations on a Func only work with the store it belongs to, and if
another store is passed in by accident then methods will panic.
Func and async
Functions from the perspective of WebAssembly are always synchronous. You
might have an async function in Rust, however, which you’d like to make
available from WebAssembly. Wasmtime supports asynchronously calling
WebAssembly through native stack switching. You can get some more
information about asynchronous configs, but
from the perspective of Func it’s important to know that whether or not
your Store is asynchronous will dictate whether you call
functions through Func::call or Func::call_async (or the typed
wrappers such as TypedFunc::call vs TypedFunc::call_async).
To Func::call or to Func::typed().call()
There’s a 2x2 matrix of methods to call Func. Invocations can either be
asynchronous or synchronous. They can also be statically typed or not.
Whether or not an invocation is asynchronous is indicated via the method
being async and call_async being the entry point.
Otherwise for statically typed or not your options are:
-
Dynamically typed - if you don’t statically know the signature of the function that you’re calling you’ll be using
Func::callorFunc::call_async. These functions take a variable-length slice of “boxed” arguments in theirValrepresentation. Additionally the results are returned as an owned slice ofVal. These methods are not optimized due to the dynamic type checks that must occur, in addition to some dynamic allocations for where to put all the arguments. While this allows you to call all possible wasm function signatures, if you’re looking for a speedier alternative you can also use… -
Statically typed - if you statically know the type signature of the wasm function you’re calling, then you’ll want to use the
Func::typedmethod to acquire an instance ofTypedFunc. This structure is static proof that the underlying wasm function has the ascripted type, and type validation is only done once up-front. TheTypedFunc::callandTypedFunc::call_asyncmethods are much more efficient thanFunc::callandFunc::call_asyncbecause the type signature is statically known. This eschews runtime checks as much as possible to get into wasm as fast as possible.
Examples
One way to get a Func is from an Instance after you’ve instantiated
it:
let engine = Engine::default();
let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let foo = instance.get_func(&mut store, "foo").expect("export wasn't a function");
// Work with `foo` as a `Func` at this point, such as calling it
// dynamically...
match foo.call(&mut store, &[]) {
Ok(result) => { /* ... */ }
Err(trap) => {
panic!("execution of `foo` resulted in a wasm trap: {}", trap);
}
}
foo.call(&mut store, &[])?;
// ... or we can make a static assertion about its signature and call it.
// Our first call here can fail if the signatures don't match, and then the
// second call can fail if the function traps (like the `match` above).
let foo = foo.typed::<(), (), _>(&store)?;
foo.call(&mut store, ())?;You can also use the wrap function to create a
Func
let mut store = Store::<()>::default();
// Create a custom `Func` which can execute arbitrary code inside of the
// closure.
let add = Func::wrap(&mut store, |a: i32, b: i32| -> i32 { a + b });
// Next we can hook that up to a wasm module which uses it.
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $add (param i32 i32) (result i32)))
(func (export "call_add_twice") (result i32)
i32.const 1
i32.const 2
call $add
i32.const 3
i32.const 4
call $add
i32.add))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[add.into()])?;
let call_add_twice = instance.get_typed_func::<(), i32, _>(&mut store, "call_add_twice")?;
assert_eq!(call_add_twice.call(&mut store, ())?, 10);Or you could also create an entirely dynamic Func!
let mut store = Store::<()>::default();
// Here we need to define the type signature of our `Double` function and
// then wrap it up in a `Func`
let double_type = wasmtime::FuncType::new(
[wasmtime::ValType::I32].iter().cloned(),
[wasmtime::ValType::I32].iter().cloned(),
);
let double = Func::new(&mut store, double_type, |_, params, results| {
let mut value = params[0].unwrap_i32();
value *= 2;
results[0] = value.into();
Ok(())
});
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $double (param i32) (result i32)))
(func $start
i32.const 1
call $double
drop)
(start $start))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[double.into()])?;
// .. work with `instance` if necessaryImplementations
Creates a new Func with the given arguments, typically to create a
host-defined function to pass as an import to a module.
-
store- the store in which to create thisFunc, which will own the return value. -
ty- the signature of this function, used to indicate what the inputs and outputs are. -
func- the native code invoked whenever thisFuncwill be called. This closure is provided aCalleras its first argument to learn information about the caller, and then it’s passed a list of parameters as a slice along with a mutable slice of where to write results.
Note that the implementation of func must adhere to the ty signature
given, error or traps may occur if it does not respect the ty
signature. For example if the function type declares that it returns one
i32 but the func closures does not write anything into the results
slice then a trap may be generated.
Additionally note that this is quite a dynamic function since signatures
are not statically known. For a more performant and ergonomic Func
it’s recommended to use Func::wrap if you can because with
statically known signatures Wasmtime can optimize the implementation
much more.
For more information about Send + Sync + 'static requirements on the
func, see Func::wrap.
Creates a new host-defined WebAssembly function which, when called,
will run the asynchronous computation defined by func to completion
and then return the result to WebAssembly.
This function is the asynchronous analogue of Func::new and much of
that documentation applies to this as well. The key difference is that
func returns a future instead of simply a Result. Note that the
returned future can close over any of the arguments, but it cannot close
over the state of the closure itself. It’s recommended to store any
necessary async state in the T of the Store<T> which
can be accessed through Caller::data or Caller::data_mut.
For more information on Send + Sync + 'static, see
Func::wrap.
Panics
This function will panic if store is not associated with an async
config.
Examples
// Simulate some application-specific state as well as asynchronous
// functions to query that state.
struct MyDatabase {
// ...
}
impl MyDatabase {
async fn get_row_count(&self) -> u32 {
// ...
}
}
let my_database = MyDatabase {
// ...
};
// Using `new_async` we can hook up into calling our async
// `get_row_count` function.
let engine = Engine::new(Config::new().async_support(true))?;
let mut store = Store::new(&engine, MyDatabase {
// ...
});
let get_row_count_type = wasmtime::FuncType::new(
None,
Some(wasmtime::ValType::I32),
);
let get = Func::new_async(&mut store, get_row_count_type, |caller, _params, results| {
Box::new(async move {
let count = caller.data().get_row_count().await;
results[0] = Val::I32(count as i32);
Ok(())
})
});
// ...pub fn wrap<T, Params, Results>(
store: impl AsContextMut<Data = T>,
func: impl IntoFunc<T, Params, Results>
) -> Func
pub fn wrap<T, Params, Results>(
store: impl AsContextMut<Data = T>,
func: impl IntoFunc<T, Params, Results>
) -> Func
Creates a new Func from the given Rust closure.
This function will create a new Func which, when called, will
execute the given Rust closure. Unlike Func::new the target
function being called is known statically so the type signature can
be inferred. Rust types will map to WebAssembly types as follows:
| Rust Argument Type | WebAssembly Type |
|---|---|
i32 | i32 |
u32 | i32 |
i64 | i64 |
u64 | i64 |
f32 | f32 |
f64 | f64 |
| (not supported) | v128 |
Option<Func> | funcref |
Option<ExternRef> | externref |
Any of the Rust types can be returned from the closure as well, in addition to some extra types
| Rust Return Type | WebAssembly Return Type | Meaning |
|---|---|---|
() | nothing | no return value |
T | T | a single return value |
(T1, T2, ...) | T1 T2 ... | multiple returns |
Note that all return types can also be wrapped in Result<_, Trap> to
indicate that the host function can generate a trap as well as possibly
returning a value.
Finally you can also optionally take Caller as the first argument of
your closure. If inserted then you’re able to inspect the caller’s
state, for example the Memory it has exported so you
can read what pointers point to.
Note that when using this API, the intention is to create as thin of a
layer as possible for when WebAssembly calls the function provided. With
sufficient inlining and optimization the WebAssembly will call straight
into func provided, with no extra fluff entailed.
Why Send + Sync + 'static?
All host functions defined in a Store (including
those from Func::new and other constructors) require that the
func provided is Send + Sync + 'static. Additionally host functions
always are Fn as opposed to FnMut or FnOnce. This can at-a-glance
feel restrictive since the closure cannot close over as many types as
before. The reason for this, though, is to ensure that
Store<T> can implement both the Send and Sync
traits.
Fear not, however, because this isn’t as restrictive as it seems! Host
functions are provided a Caller<'_, T> argument which
allows access to the host-defined data within the
Store. The T type is not required to be any of
Send, Sync, or 'static! This means that you can store whatever
you’d like in T and have it accessible by all host functions.
Additionally mutable access to T is allowed through
Caller::data_mut.
Most host-defined Func values provide closures that end up not
actually closing over any values. These zero-sized types will use the
context from Caller for host-defined information.
Examples
First up we can see how simple wasm imports can be implemented, such as a function that adds its two arguments and returns the result.
let add = Func::wrap(&mut store, |a: i32, b: i32| a + b);
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $add (param i32 i32) (result i32)))
(func (export "foo") (param i32 i32) (result i32)
local.get 0
local.get 1
call $add))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[add.into()])?;
let foo = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "foo")?;
assert_eq!(foo.call(&mut store, (1, 2))?, 3);We can also do the same thing, but generate a trap if the addition overflows:
let add = Func::wrap(&mut store, |a: i32, b: i32| {
match a.checked_add(b) {
Some(i) => Ok(i),
None => Err(Trap::new("overflow")),
}
});
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $add (param i32 i32) (result i32)))
(func (export "foo") (param i32 i32) (result i32)
local.get 0
local.get 1
call $add))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[add.into()])?;
let foo = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "foo")?;
assert_eq!(foo.call(&mut store, (1, 2))?, 3);
assert!(foo.call(&mut store, (i32::max_value(), 1)).is_err());And don’t forget all the wasm types are supported!
let debug = Func::wrap(&mut store, |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
println!("a={}", a);
println!("b={}", b);
println!("c={}", c);
println!("d={}", d);
println!("e={}", e);
println!("f={}", f);
});
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
(func (export "foo")
i32.const -1
i32.const 1
f32.const 2
i64.const -3
i64.const 3
f64.const 4
call $debug))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[debug.into()])?;
let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
foo.call(&mut store, ())?;Finally if you want to get really fancy you can also implement imports that read/write wasm module’s memory
use std::str;
let log_str = Func::wrap(&mut store, |mut caller: Caller<'_, ()>, ptr: i32, len: i32| {
let mem = match caller.get_export("memory") {
Some(Extern::Memory(mem)) => mem,
_ => return Err(Trap::new("failed to find host memory")),
};
let data = mem.data(&caller)
.get(ptr as u32 as usize..)
.and_then(|arr| arr.get(..len as u32 as usize));
let string = match data {
Some(data) => match str::from_utf8(data) {
Ok(s) => s,
Err(_) => return Err(Trap::new("invalid utf-8")),
},
None => return Err(Trap::new("pointer/length out of bounds")),
};
assert_eq!(string, "Hello, world!");
println!("{}", string);
Ok(())
});
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (func $log_str (param i32 i32)))
(func (export "foo")
i32.const 4 ;; ptr
i32.const 13 ;; len
call $log_str)
(memory (export "memory") 1)
(data (i32.const 4) "Hello, world!"))
"#,
)?;
let instance = Instance::new(&mut store, &module, &[log_str.into()])?;
let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
foo.call(&mut store, ())?;Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap5_async<T, A1, A2, A3, A4, A5, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
R: WasmRet,
pub fn wrap5_async<T, A1, A2, A3, A4, A5, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap6_async<T, A1, A2, A3, A4, A5, A6, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
R: WasmRet,
pub fn wrap6_async<T, A1, A2, A3, A4, A5, A6, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap7_async<T, A1, A2, A3, A4, A5, A6, A7, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
R: WasmRet,
pub fn wrap7_async<T, A1, A2, A3, A4, A5, A6, A7, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap8_async<T, A1, A2, A3, A4, A5, A6, A7, A8, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
R: WasmRet,
pub fn wrap8_async<T, A1, A2, A3, A4, A5, A6, A7, A8, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap9_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
R: WasmRet,
pub fn wrap9_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap10_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
R: WasmRet,
pub fn wrap10_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap11_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
R: WasmRet,
pub fn wrap11_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap12_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
R: WasmRet,
pub fn wrap12_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap13_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
R: WasmRet,
pub fn wrap13_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap14_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
R: WasmRet,
pub fn wrap14_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap15_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
A15: WasmTy,
R: WasmRet,
pub fn wrap15_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
A15: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
pub fn wrap16_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
A15: WasmTy,
A16: WasmTy,
R: WasmRet,
pub fn wrap16_async<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, R>(
store: impl AsContextMut<Data = T>,
func: impl for<'a> Fn(Caller<'a, T>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) -> Box<dyn Future<Output = R> + Send + 'a, Global> + Send + Sync + 'static
) -> Func where
A1: WasmTy,
A2: WasmTy,
A3: WasmTy,
A4: WasmTy,
A5: WasmTy,
A6: WasmTy,
A7: WasmTy,
A8: WasmTy,
A9: WasmTy,
A10: WasmTy,
A11: WasmTy,
A12: WasmTy,
A13: WasmTy,
A14: WasmTy,
A15: WasmTy,
A16: WasmTy,
R: WasmRet,
Same as Func::wrap, except the closure asynchronously produces
its result. For more information see the Func documentation.
Panics
This function will panic if called with a non-asynchronous store.
Returns the underlying wasm type that this Func has.
Panics
Panics if store does not own this function.
Invokes this function with the params given, returning the results and
any trap, if one occurs.
The params here must match the type signature of this Func, or a
trap will occur. If a trap occurs while executing this function, then a
trap will also be returned.
Panics
This function will panic if called on a function belonging to an async
store. Asynchronous stores must always use call_async.
initiates a panic. Also panics if store does not own this function.
Invokes this function with the params given, returning the results
asynchronously.
This function is the same as Func::call except that it is
asynchronous. This is only compatible with stores associated with an
asynchronous config.
It’s important to note that the execution of WebAssembly will happen
synchronously in the poll method of the future returned from this
function. Wasmtime does not manage its own thread pool or similar to
execute WebAssembly in. Future poll methods are generally expected to
resolve quickly, so it’s recommended that you run or poll this future
in a “blocking context”.
For more information see the documentation on asynchronous configs.
Panics
Panics if this is called on a function in a synchronous store. This
only works with functions defined within an asynchronous store. Also
panics if store does not own this function.
pub fn typed<Params, Results, S>(
&self,
store: S
) -> Result<TypedFunc<Params, Results>, Error> where
Params: WasmParams,
Results: WasmResults,
S: AsContext,
pub fn typed<Params, Results, S>(
&self,
store: S
) -> Result<TypedFunc<Params, Results>, Error> where
Params: WasmParams,
Results: WasmResults,
S: AsContext,
Attempts to extract a typed object from this Func through which the
function can be called.
This function serves as an alternative to Func::call and
Func::call_async. This method performs a static type check (using
the Params and Results type parameters on the underlying wasm
function. If the type check passes then a TypedFunc object is returned,
otherwise an error is returned describing the typecheck failure.
The purpose of this relative to Func::call is that it’s much more
efficient when used to invoke WebAssembly functions. With the types
statically known far less setup/teardown is required when invoking
WebAssembly. If speed is desired then this function is recommended to be
used instead of Func::call (which is more general, hence its
slowdown).
The Params type parameter is used to describe the parameters of the
WebAssembly function. This can either be a single type (like i32), or
a tuple of types representing the list of parameters (like (i32, f32, f64)). Additionally you can use () to represent that the function has
no parameters.
The Results type parameter is used to describe the results of the
function. This behaves the same way as Params, but just for the
results of the function.
The S type parameter represents the method of passing in the store
context, and can typically be specified as simply _ when calling this
function.
Translation between Rust types and WebAssembly types looks like:
| WebAssembly | Rust |
|---|---|
i32 | i32 or u32 |
i64 | i64 or u64 |
f32 | f32 |
f64 | f64 |
externref | Option<ExternRef> |
funcref | Option<Func> |
v128 | not supported |
(note that this mapping is the same as that of Func::wrap).
Note that once the TypedFunc return value is acquired you’ll use either
TypedFunc::call or TypedFunc::call_async as necessary to actually invoke
the function. This method does not invoke any WebAssembly code, it
simply performs a typecheck before returning the TypedFunc value.
This method also has a convenience wrapper as
Instance::get_typed_func to
directly get a typed function value from an
Instance.
Errors
This function will return an error if Params or Results does not
match the native type of this WebAssembly function.
Panics
This method will panic if store does not own this function.
Examples
An end-to-end example of calling a function which takes no parameters and has no results:
let engine = Engine::default();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
let instance = Instance::new(&mut store, &module, &[])?;
let foo = instance.get_func(&mut store, "foo").expect("export wasn't a function");
// Note that this call can fail due to the typecheck not passing, but
// in our case we statically know the module so we know this should
// pass.
let typed = foo.typed::<(), (), _>(&store)?;
// Note that this can fail if the wasm traps at runtime.
typed.call(&mut store, ())?;You can also pass in multiple parameters and get a result back
let typed = add.typed::<(i32, i64), f32, _>(&store)?;
assert_eq!(typed.call(&mut store, (1, 2))?, 3.0);and similarly if a function has multiple results you can bind that too
let typed = add_with_overflow.typed::<(u32, u32), (u32, i32), _>(&store)?;
let (result, overflow) = typed.call(&mut store, (u32::max_value(), 2))?;
assert_eq!(result, 1);
assert_eq!(overflow, 1);Trait Implementations
Auto Trait Implementations
impl RefUnwindSafe for Func
impl UnwindSafe for Func
Blanket Implementations
Mutably borrows from an owned value. Read more
Attaches the provided Subscriber to this type, returning a
WithDispatch wrapper. Read more
Attaches the current default Subscriber to this type, returning a
WithDispatch wrapper. Read more