#[repr(C)]
pub struct Func { }
Available on crate feature runtime
only.
A WebAssembly function which can be called.
This type typically represents an exported function from a WebAssembly module instance. In this case a Func
belongs to an Instance
and is loaded from there. A Func
may also represent a host function as well in some cases, too.
Functions can be called in a few different ways, either synchronous or async and either typed or untyped (more on this below). Note that host functions are normally inserted directly into a Linker
rather than using this directly, but both options are available.
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
).
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::call
or Func::call_async
. These functions take a variable-length slice of “boxed” arguments in their Val
representation. Additionally the results are returned as an owned slice of Val
. 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::typed
method to acquire an instance of TypedFunc
. This structure is static proof that the underlying wasm function has the ascripted type, and type validation is only done once up-front. The TypedFunc::call
and TypedFunc::call_async
methods are much more efficient than Func::call
and Func::call_async
because the type signature is statically known. This eschews runtime checks as much as possible to get into wasm as fast as possible.
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");
match foo.call(&mut store, &[], &mut []) {
Ok(()) => { }
Err(trap) => {
panic!("execution of `foo` resulted in a wasm trap: {}", trap);
}
}
foo.call(&mut store, &[], &mut [])?;
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();
let add = Func::wrap(&mut store, |a: i32, b: i32| -> i32 { a + b });
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();
let double_type = wasmtime::FuncType::new(
store.engine(),
[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()])?;
Source§ Source
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 this Func
, 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 this Func
will be called. This closure is provided a Caller
as 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
.
The host-provided function here returns a Result<()>
. If the function returns Ok(())
then that indicates that the host function completed successfully and wrote the result into the &mut [Val]
argument.
If the function returns Err(e)
, however, then this is equivalent to the host function triggering a trap for wasm. WebAssembly execution is immediately halted and the original caller of Func::call
, for example, will receive the error returned here (possibly with WasmBacktrace
context information attached).
For more information about errors in Wasmtime see the Trap
documentation.
Panics if the given function type is not associated with this store’s engine.
SourceCreates a new Func
with the given arguments, although has fewer runtime checks than Func::new
.
This function takes a callback of a different signature than Func::new
, instead receiving a raw pointer with a list of ValRaw
structures. These values have no type information associated with them so it’s up to the caller to provide a function that will correctly interpret the list of values as those coming from the ty
specified.
If you’re calling this from Rust it’s recommended to either instead use Func::new
or Func::wrap
. The Func::wrap
API, in particular, is both safer and faster than this API.
See Func::new
for the behavior of returning an error from the host function provided here.
This function is not safe because it’s not known at compile time that the func
provided correctly interprets the argument types provided to it, or that the results it produces will be of the correct type.
Panics if the given function type is not associated with this store’s engine.
SourceAvailable on crate features async
and cranelift
only.
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
.
This function will panic if store
is not associated with an async config.
Panics if the given function type is not associated with this store’s engine.
§ErrorsSee Func::new
for the behavior of returning an error from the host function provided here.
struct MyDatabase {
}
impl MyDatabase {
async fn get_row_count(&self) -> u32 {
}
}
let my_database = MyDatabase {
};
let engine = Engine::new(Config::new().async_support(true))?;
let mut store = Store::new(&engine, MyDatabase {
});
let get_row_count_type = wasmtime::FuncType::new(
&engine,
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(())
})
});
Source
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:
i32
i32
u32
i32
i64
i64
u64
i64
f32
f32
f64
f64
V128
on x86-64 and aarch64 only v128
Option<Func>
funcref
aka (ref null func)
Func
(ref func)
Option<Nofunc>
nullfuncref
aka (ref null nofunc)
NoFunc
(ref nofunc)
Option<Rooted<ExternRef>>
externref
aka (ref null extern)
Rooted<ExternRef>
(ref extern)
Option<NoExtern>
nullexternref
aka (ref null noextern)
NoExtern
(ref noextern)
Option<Rooted<AnyRef>>
anyref
aka (ref null any)
Rooted<AnyRef>
(ref any)
Option<Rooted<EqRef>>
eqref
aka (ref null eq)
Rooted<EqRef>
(ref eq)
Option<I31>
i31ref
aka (ref null i31)
I31
(ref i31)
Option<Rooted<StructRef>>
(ref null struct)
Rooted<StructRef>
(ref struct)
Option<Rooted<ArrayRef>>
(ref null array)
Rooted<ArrayRef>
(ref array)
Option<NoneRef>
nullref
aka (ref null none)
NoneRef
(ref none)
Note that anywhere a Rooted<T>
appears, a ManuallyRooted<T>
may also be used.
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<_>
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.
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.
The closure provided here to wrap
can optionally return a Result<T>
. Returning Ok(t)
represents the host function successfully completing with the t
result. Returning Err(e)
, however, is equivalent to raising a custom wasm trap. Execution of WebAssembly does not resume and the stack is unwound to the original caller of the function where the error is returned.
For more information about errors in Wasmtime see the Trap
documentation.
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 => anyhow::bail!("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,
_ => anyhow::bail!("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(_) => anyhow::bail!("invalid utf-8"),
},
None => anyhow::bail!("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, ())?;
Source
Available on crate feature async
only.
Same as Func::wrap
, except the closure asynchronously produces the result and the arguments are passed within a tuple. For more information see the Func
documentation.
This function will panic if called with a non-asynchronous store.
SourceReturns the underlying wasm type that this Func
has.
Panics if store
does not own this function.
Does this function match the given type?
That is, is this function’s type a subtype of the given type?
§PanicsPanics if this function is not associated with the given store or if the function type is not associated with the store’s engine.
SourceInvokes this function with the params
given and writes returned values to results
.
The params
here must match the type signature of this Func
, or an error will occur. Additionally results
must have the same length as the number of results for this function. Calling this function will synchronously execute the WebAssembly function referenced to get the results.
This function will return Ok(())
if execution completed without a trap or error of any kind. In this situation the results will be written to the provided results
array.
Any error which occurs throughout the execution of the function will be returned as Err(e)
. The Error
type can be inspected for the precise error cause such as:
Trap
- indicates that a wasm trap happened and execution was halted.WasmBacktrace
- optionally included on errors for backtrace information of the trap/error.params
.Func::new
, for example.Errors typically indicate that execution of WebAssembly was halted mid-way and did not complete after the error condition happened.
§PanicsThis function will panic if called on a function belonging to an async store. Asynchronous stores must always use call_async
. Also panics if store
does not own this function.
Invokes this function in an “unchecked” fashion, reading parameters and writing results to params_and_returns
.
This function is the same as Func::call
except that the arguments and results both use a different representation. If possible it’s recommended to use Func::call
if safety isn’t necessary or to use Func::typed
in conjunction with TypedFunc::call
since that’s both safer and faster than this method of invoking a function.
Note that if this function takes externref
arguments then it will not automatically GC unlike the Func::call
and TypedFunc::call
functions. This means that if this function is invoked many times with new ExternRef
values and no other GC happens via any other means then no values will get collected.
For more information about errors see the Func::call
documentation.
This function is unsafe because the params_and_returns
argument is not validated at all. It must uphold invariants such as:
externref
and funcref
are valid at the time of this call and for the store
specified.These invariants are all upheld for you with Func::call
and TypedFunc::call
.
Converts the raw representation of a funcref
into an Option<Func>
This is intended to be used in conjunction with Func::new_unchecked
, Func::call_unchecked
, and ValRaw
with its funcref
field. This is the dual of Func::to_raw
.
This function is not safe because raw
is not validated at all. The caller must guarantee that raw
is owned by the store
provided and is valid within the store
.
Extracts the raw value of this Func
, which is owned by store
.
This function returns a value that’s suitable for writing into the funcref
field of the ValRaw
structure.
The returned value is only valid for as long as the store is alive. This value is safe to pass to Func::from_raw
so long as the same store
is provided.
Available on crate feature async
only.
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.
§ErrorsFor more information on errors see the Func::call
documentation.
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.
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.
Translation between Rust types and WebAssembly types looks like:
WebAssembly Rusti32
i32
or u32
i64
i64
or u64
f32
f32
f64
f64
externref
aka (ref null extern)
Option<Rooted<ExternRef>>
(ref extern)
Rooted<ExternRef>
nullexternref
aka (ref null noextern)
Option<NoExtern>
(ref noextern)
NoExtern
anyref
aka (ref null any)
Option<Rooted<AnyRef>>
(ref any)
Rooted<AnyRef>
eqref
aka (ref null eq)
Option<Rooted<EqRef>>
(ref eq)
Rooted<EqRef>
i31ref
aka (ref null i31)
Option<I31>
(ref i31)
I31
structref
aka (ref null struct)
Option<Rooted<StructRef>>
(ref struct)
Rooted<StructRef>
arrayref
aka (ref null array)
Option<Rooted<ArrayRef>>
(ref array)
Rooted<ArrayRef>
nullref
aka (ref null none)
Option<NoneRef>
(ref none)
NoneRef
funcref
aka (ref null func)
Option<Func>
(ref func)
Func
(ref null <func type index>)
Option<Func>
(ref <func type index>)
Func
nullfuncref
aka (ref null nofunc)
Option<NoFunc>
(ref nofunc)
NoFunc
v128
V128
on x86-64
and aarch64
only
(Note that this mapping is the same as that of Func::wrap
, and that anywhere a Rooted<T>
appears, a ManuallyRooted<T>
may also appear).
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
.
For result types, you can always use a supertype of the WebAssembly function’s actual declared result type. For example, if the WebAssembly function was declared with type (func (result nullfuncref))
you could successfully call f.typed::<(), Option<Func>>()
because Option<Func>
corresponds to funcref
, which is a supertype of nullfuncref
.
For parameter types, you can always use a subtype of the WebAssembly function’s actual declared parameter type. For example, if the WebAssembly function was declared with type (func (param (ref null func)))
you could successfully call f.typed::<Func, ()>()
because Func
corresponds to (ref func)
, which is a subtype of (ref null func)
.
Additionally, for functions which take a reference to a concrete type as a parameter, you can also use the concrete type’s supertype. Consider a WebAssembly function that takes a reference to a function with a concrete type: (ref null <func type index>)
. In this scenario, there is no static wasmtime::Foo
Rust type that corresponds to that particular Wasm-defined concrete reference type because Wasm modules are loaded dynamically at runtime. You could do f.typed::<Option<NoFunc>, ()>()
, and while that is correctly typed and valid, it is often overly restrictive. The only value you could call the resulting typed function with is the null function reference, but we’d like to call it with non-null function references that happen to be of the correct type. Therefore, f.typed<Option<Func>, ()>()
is also allowed in this case, even though Option<Func>
represents (ref null func)
which is the supertype, not subtype, of (ref null <func type index>)
. This does imply some minimal dynamic type checks in this case, but it is supported for better ergonomics, to enable passing non-null references into the function.
This function will return an error if Params
or Results
does not match the native type of this WebAssembly function.
This method will panic if store
does not own this function.
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");
let typed = foo.typed::<(), ()>(&store)?;
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);
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