Struct wasmtime::Func[][src]

pub struct Func { /* fields omitted */ }
Expand description

A WebAssembly function which can be called.

This type can represent a number of callable items, such as:

  • An exported function from a WebAssembly module.
  • A user-defined function used to satisfy an import.

These types of callable items are all wrapped up in this Func and can be used to both instantiate an Instance as well as be extracted from an Instance.

Func and Clone

Functions are internally reference counted so you can clone a Func. The cloning process only performs a shallow clone, so two cloned Func instances are equivalent in their functionality.

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).

Note that asynchronous function APIs here are a bit trickier than their synchronous brethren. For example Func::new_async and Func::wrapN_async take explicit state parameters to allow you to close over the state in the returned future. It’s recommended that you pass state via these parameters instead of through the closure’s environment, which may give Rust lifetime errors. Additionally unlike synchronous functions which can all get wrapped through Func::wrap asynchronous functions need to explicitly wrap based on the number of parameters that they have (e.g. no wasm parameters gives you Func::wrap0_async, one wasm parameter you’d use Func::wrap1_async, etc). Be sure to consult the documentation for Func::wrap for how the wasm type signature is inferred from the Rust type signature.

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::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.

Examples

One way to get a Func is from an Instance after you’ve instantiated it:

let engine = Engine::default();
let store = Store::new(&engine);
let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
let instance = Instance::new(&store, &module, &[])?;
let foo = instance.get_func("foo").expect("export wasn't a function");

// Work with `foo` as a `Func` at this point, such as calling it
// dynamically...
match foo.call(&[]) {
    Ok(result) => { /* ... */ }
    Err(trap) => {
        panic!("execution of `foo` resulted in a wasm trap: {}", trap);
    }
}
foo.call(&[])?;

// ... 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::<(), ()>()?;
foo.call(())?;

You can also use the wrap function to create a Func

let store = Store::default();

// Create a custom `Func` which can execute arbitrary code inside of the
// closure.
let add = Func::wrap(&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(&store, &module, &[add.into()])?;
let call_add_twice = instance.get_typed_func::<(), i32>("call_add_twice")?;

assert_eq!(call_add_twice.call(())?, 10);

Or you could also create an entirely dynamic Func!

let 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(&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(&store, &module, &[double.into()])?;
// .. work with `instance` if necessary

Implementations

impl Func[src]

pub fn new(
    store: &Store,
    ty: FuncType,
    func: impl Fn(Caller<'_>, &[Val], &mut [Val]) -> Result<(), Trap> + 'static
) -> Self
[src]

Creates a new Func with the given arguments, typically to create a user-defined function to pass as an import to a module.

  • store - a cache of data where information is stored, typically shared with a Module.

  • ty - the signature of this function, used to indicate what the inputs and outputs are, which must be WebAssembly types.

  • 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.

Additionally note that this is quite a dynamic function since signatures are not statically known. For a more performant Func it’s recommended to use Func::wrap if you can because with statically known signatures the engine can optimize the implementation much more.

pub fn new_async<T, F>(store: &Store, ty: FuncType, state: T, func: F) -> Func where
    T: 'static,
    F: for<'a> Fn(Caller<'a>, &'a T, &'a [Val], &'a mut [Val]) -> Box<dyn Future<Output = Result<(), Trap>> + 'a> + 'static, 
[src]

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. There are a few key differences (besides being asynchronous) that are worth pointing out:

  • The state parameter T is passed to the provided function F on each invocation. This is done so you can use the state in T in the computation of the output future (the future can close over this value). Unfortunately due to limitations of async-in-Rust right now you cannot close over the captured variables in F itself in the returned future. This means that you likely won’t close over much state in F and will instead use T.

  • The closure here returns a boxed future, not something that simply implements a future. This is also unfortunately due to limitations in Rust right now.

Overall we’re not super happy with this API signature and would love to change it to make it more ergonomic. Despite this, however, you should be able to still hook into asynchronous computations and plug them into wasm. Improvements are always welcome with PRs!

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 store = Store::new(&Engine::new(Config::new().async_support(true))?);
let get_row_count_type = wasmtime::FuncType::new(
    None,
    Some(wasmtime::ValType::I32),
);
let double = Func::new_async(&store, get_row_count_type, my_database, |_, database, params, results| {
    Box::new(async move {
        let count = database.get_row_count().await;
        results[0] = Val::I32(count as i32);
        Ok(())
    })
});
// ...

pub fn wrap<Params, Results>(
    store: &Store,
    func: impl IntoFunc<Params, Results>
) -> Func
[src]

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 TypeWebAssembly Type
i32i32
u32i32
i64i64
u64i64
f32f32
f64f64
(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 TypeWebAssembly Return TypeMeaning
()nothingno return value
TTa 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.

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(&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(&store, &module, &[add.into()])?;
let foo = instance.get_typed_func::<(i32, i32), i32>("foo")?;
assert_eq!(foo.call((1, 2))?, 3);

We can also do the same thing, but generate a trap if the addition overflows:

let add = Func::wrap(&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(&store, &module, &[add.into()])?;
let foo = instance.get_typed_func::<(i32, i32), i32>("foo")?;
assert_eq!(foo.call((1, 2))?, 3);
assert!(foo.call((i32::max_value(), 1)).is_err());

And don’t forget all the wasm types are supported!

let debug = Func::wrap(&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(&store, &module, &[debug.into()])?;
let foo = instance.get_typed_func::<(), ()>("foo")?;
foo.call(())?;

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(&store, |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")),
    };

    // We're reading raw wasm memory here so we need `unsafe`. Note
    // though that this should be safe because we don't reenter wasm
    // while we're reading wasm memory, nor should we clash with
    // any other memory accessors (assuming they're well-behaved
    // too).
    unsafe {
        let data = mem.data_unchecked()
            .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(&store, &module, &[log_str.into()])?;
let foo = instance.get_typed_func::<(), ()>("foo")?;
foo.call(())?;

pub fn wrap0_async<T, R>(
    store: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    R: WasmRet
[src]

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 wrap1_async<T, A1, R>(
    store: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    R: WasmRet
[src]

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 wrap2_async<T, A1, A2, R>(
    store: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    R: WasmRet
[src]

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 wrap3_async<T, A1, A2, A3, R>(
    store: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    R: WasmRet
[src]

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 wrap4_async<T, A1, A2, A3, A4, R>(
    store: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    A7: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    A7: WasmTy,
    A8: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    A7: WasmTy,
    A8: WasmTy,
    A9: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    A7: WasmTy,
    A8: WasmTy,
    A9: WasmTy,
    A10: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    A1: WasmTy,
    A2: WasmTy,
    A3: WasmTy,
    A4: WasmTy,
    A5: WasmTy,
    A6: WasmTy,
    A7: WasmTy,
    A8: WasmTy,
    A9: WasmTy,
    A10: WasmTy,
    A11: WasmTy,
    R: WasmRet
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    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
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    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
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    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
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    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
[src]

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: &Store,
    state: T,
    func: impl for<'a> Fn(Caller<'a>, &'a T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) -> Box<dyn Future<Output = R> + 'a> + 'static
) -> Func where
    T: 'static,
    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
[src]

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 ty(&self) -> FuncType[src]

Returns the underlying wasm type that this Func has.

pub fn param_arity(&self) -> usize[src]

Returns the number of parameters that this function takes.

pub fn result_arity(&self) -> usize[src]

Returns the number of results this function produces.

pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>>[src]

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.

pub async fn call_async(&self, params: &[Val]) -> Result<Box<[Val]>>[src]

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.

pub fn store(&self) -> &Store[src]

Get a reference to this function’s store.

pub fn typed<Params, Results>(&self) -> Result<&TypedFunc<Params, Results>> where
    Params: WasmParams,
    Results: WasmResults
[src]

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:

WebAssemblyRust
i32i32 or u32
i64i64 or u64
f32f32
f64f64
externrefOption<ExternRef>
funcrefOption<Func>
v128not 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.

Examples

An end-to-end example of calling a function which takes no parameters and has no results:

let engine = Engine::default();
let store = Store::new(&engine);
let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
let instance = Instance::new(&store, &module, &[])?;
let foo = instance.get_func("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::<(), ()>()?;

// Note that this can fail if the wasm traps at runtime.
typed.call(())?;

You can also pass in multiple parameters and get a result back

let typed = add.typed::<(i32, i64), f32>()?;
assert_eq!(typed.call((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)>()?;
let (result, overflow) = typed.call((u32::max_value(), 2))?;
assert_eq!(result, 1);
assert_eq!(overflow, 1);

pub unsafe fn typed_unchecked<Params, Results>(
    &self
) -> &TypedFunc<Params, Results> where
    Params: WasmParams,
    Results: WasmResults
[src]

An unchecked version of Func::typed which does not perform a typecheck and simply assumes that the type declared here matches the type of this function.

The semantics of this function are the same as Func::typed except that no error is returned because no typechecking is done.

Unsafety

This function only safe to call if typed would otherwise return Ok for the same Params and Results specified. If typed would return an error then the returned TypedFunc is memory unsafe to invoke.

Trait Implementations

impl Clone for Func[src]

fn clone(&self) -> Func[src]

Returns a copy of the value. Read more

fn clone_from(&mut self, source: &Self)1.0.0[src]

Performs copy-assignment from source. Read more

impl Debug for Func[src]

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter. Read more

impl From<Func> for Extern[src]

fn from(r: Func) -> Self[src]

Performs the conversion.

impl From<Func> for Val[src]

fn from(val: Func) -> Val[src]

Performs the conversion.

Auto Trait Implementations

impl !RefUnwindSafe for Func

impl !Send for Func

impl !Sync for Func

impl Unpin for Func

impl !UnwindSafe for Func

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

pub fn type_id(&self) -> TypeId[src]

Gets the TypeId of self. Read more

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

pub fn borrow(&self) -> &T[src]

Immutably borrows from an owned value. Read more

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

pub fn borrow_mut(&mut self) -> &mut T[src]

Mutably borrows from an owned value. Read more

impl<T> From<T> for T[src]

pub fn from(t: T) -> T[src]

Performs the conversion.

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

pub fn into(self) -> U[src]

Performs the conversion.

impl<T> Pointable for T

pub const ALIGN: usize

The alignment of pointer.

type Init = T

The type for initializers.

pub unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more

pub unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more

pub unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more

pub unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more

impl<T> Same<T> for T

type Output = T

Should always be Self

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

pub fn to_owned(&self) -> T[src]

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

pub fn clone_into(&self, target: &mut T)[src]

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

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

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

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

Performs the conversion.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.

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

Performs the conversion.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

pub fn vzip(self) -> V