Struct wasmtime::Instance

source ·
#[repr(transparent)]
pub struct Instance(_);
Expand description

An instantiated WebAssembly module.

This type represents the instantiation of a Module. Once instantiated you can access the exports which are of type Extern and provide the ability to call functions, set globals, read memory, etc. When interacting with any wasm code you’ll want to make an Instance to call any code or execute anything.

Instances are owned by a Store which is passed in at creation time. It’s recommended to create instances with Linker::instantiate or similar Linker methods, but a more low-level constructor is also available as Instance::new.

Implementations§

Creates a new Instance from the previously compiled Module and list of imports specified.

This method instantiates the module provided with the imports, following the procedure in the core specification to instantiate. Instantiation can fail for a number of reasons (many specified below), but if successful the start function will be automatically run (if specified in the module) and then the Instance will be returned.

Per the WebAssembly spec, instantiation includes running the module’s start function, if it has one (not to be confused with the _start function, which is not run).

Note that this is a low-level function that just performs an instantiation. See the Linker struct for an API which provides a convenient way to link imports and provides automatic Command and Reactor behavior.

Providing Imports

The entries in the list of imports are intended to correspond 1:1 with the list of imports returned by Module::imports. Before calling Instance::new you’ll want to inspect the return value of Module::imports and, for each import type, create an Extern which corresponds to that type. These Extern values are all then collected into a list and passed to this function.

Note that this function is intentionally relatively low level. For an easier time passing imports by doing name-based resolution it’s recommended to instead use the Linker type.

Errors

This function can fail for a number of reasons, including, but not limited to:

  • The number of imports provided doesn’t match the number of imports returned by the module’s Module::imports method.
  • The type of any Extern doesn’t match the corresponding ExternType entry that it maps to.
  • The start function in the instance, if present, traps.
  • Module/instance resource limits are exceeded.

When instantiation fails it’s recommended to inspect the return value to see why it failed, or bubble it upwards. If you’d like to specifically check for trap errors, you can use error.downcast::<Trap>(). For more about error handling see the Trap documentation.

Panics

This function will panic if called with a store associated with a asynchronous config. This function will also panic if any Extern supplied is not owned by store.

Available on crate feature async only.

Same as Instance::new, except for usage in [asynchronous stores].

For more details about this function see the documentation on Instance::new. The only difference between these two methods is that this one will asynchronously invoke the wasm start function in case it calls any imported function which is an asynchronous host function (e.g. created with Func::new_async.

Panics

This function will panic if called with a store associated with a synchronous config. This is only compatible with stores associated with an asynchronous config.

This function will also panic, like Instance::new, if any Extern specified does not belong to store.

Examples found in repository?
src/lib.rs (line 473)
472
473
474
    fn _instantiate_async(s: &mut Store<()>, m: &Module) {
        _assert_send(Instance::new_async(s, m, &[]))
    }

Returns the list of exported items from this Instance.

Panics

Panics if store does not own this instance.

Examples found in repository?
src/linker.rs (line 550)
544
545
546
547
548
549
550
551
552
553
554
555
    pub fn instance(
        &mut self,
        mut store: impl AsContextMut<Data = T>,
        module_name: &str,
        instance: Instance,
    ) -> Result<&mut Self> {
        for export in instance.exports(store.as_context_mut()) {
            let key = self.import_key(module_name, Some(export.name()));
            self.insert(key, Definition::Extern(export.into_extern()))?;
        }
        Ok(self)
    }

Looks up an exported Extern value by name.

This method will search the module for an export named name and return the value, if found.

Returns None if there was no export named name.

Panics

Panics if store does not own this instance.

Why does get_export take a mutable context?

This method requires a mutable context because an instance’s exports are lazily populated, and we cache them as they are accessed. This makes instantiating a module faster, but also means this method requires a mutable context.

Examples found in repository?
src/instance.rs (line 439)
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    pub fn get_func(&self, store: impl AsContextMut, name: &str) -> Option<Func> {
        self.get_export(store, name)?.into_func()
    }

    /// Looks up an exported [`Func`] value by name and with its type.
    ///
    /// This function is a convenience wrapper over [`Instance::get_func`] and
    /// [`Func::typed`]. For more information see the linked documentation.
    ///
    /// Returns an error if `name` isn't a function export or if the export's
    /// type did not match `Params` or `Results`
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this instance.
    pub fn get_typed_func<Params, Results>(
        &self,
        mut store: impl AsContextMut,
        name: &str,
    ) -> Result<TypedFunc<Params, Results>>
    where
        Params: crate::WasmParams,
        Results: crate::WasmResults,
    {
        let f = self
            .get_export(store.as_context_mut(), name)
            .and_then(|f| f.into_func())
            .ok_or_else(|| anyhow!("failed to find function export `{}`", name))?;
        Ok(f.typed::<Params, Results>(store)
            .with_context(|| format!("failed to convert function `{}` to given type", name))?)
    }

    /// Looks up an exported [`Table`] value by name.
    ///
    /// Returns `None` if there was no export named `name`, or if there was but
    /// it wasn't a table.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this instance.
    pub fn get_table(&self, store: impl AsContextMut, name: &str) -> Option<Table> {
        self.get_export(store, name)?.into_table()
    }

    /// Looks up an exported [`Memory`] value by name.
    ///
    /// Returns `None` if there was no export named `name`, or if there was but
    /// it wasn't a memory.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this instance.
    pub fn get_memory(&self, store: impl AsContextMut, name: &str) -> Option<Memory> {
        self.get_export(store, name)?.into_memory()
    }

    /// Looks up an exported [`SharedMemory`] value by name.
    ///
    /// Returns `None` if there was no export named `name`, or if there was but
    /// it wasn't a shared memory.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this instance.
    pub fn get_shared_memory(
        &self,
        mut store: impl AsContextMut,
        name: &str,
    ) -> Option<SharedMemory> {
        let mut store = store.as_context_mut();
        self.get_export(&mut store, name)?.into_shared_memory()
    }

    /// Looks up an exported [`Global`] value by name.
    ///
    /// Returns `None` if there was no export named `name`, or if there was but
    /// it wasn't a global.
    ///
    /// # Panics
    ///
    /// Panics if `store` does not own this instance.
    pub fn get_global(&self, store: impl AsContextMut, name: &str) -> Option<Global> {
        self.get_export(store, name)?.into_global()
    }
More examples
Hide additional examples
src/func.rs (line 1760)
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
    pub fn get_export(&mut self, name: &str) -> Option<Extern> {
        // All instances created have a `host_state` with a pointer pointing
        // back to themselves. If this caller doesn't have that `host_state`
        // then it probably means it was a host-created object like `Func::new`
        // which doesn't have any exports we want to return anyway.
        self.caller
            .host_state()
            .downcast_ref::<Instance>()?
            .get_export(&mut self.store, name)
    }
src/linker.rs (line 713)
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
    pub fn module(
        &mut self,
        mut store: impl AsContextMut<Data = T>,
        module_name: &str,
        module: &Module,
    ) -> Result<&mut Self>
    where
        T: 'static,
    {
        // NB: this is intended to function the same as `Linker::module_async`,
        // they should be kept in sync.

        // This assert isn't strictly necessary since it'll bottom out in the
        // `HostFunc::to_func` method anyway. This is placed earlier for this
        // function though to prevent the functions created here from delaying
        // the panic until they're called.
        assert!(
            Engine::same(&self.engine, store.as_context().engine()),
            "different engines for this linker and the store provided"
        );
        match ModuleKind::categorize(module)? {
            ModuleKind::Command => {
                self.command(
                    store,
                    module_name,
                    module,
                    |store, func_ty, export_name, instance_pre| {
                        Func::new(
                            store,
                            func_ty.clone(),
                            move |mut caller, params, results| {
                                // Create a new instance for this command execution.
                                let instance = instance_pre.instantiate(&mut caller)?;

                                // `unwrap()` everything here because we know the instance contains a
                                // function export with the given name and signature because we're
                                // iterating over the module it was instantiated from.
                                instance
                                    .get_export(&mut caller, &export_name)
                                    .unwrap()
                                    .into_func()
                                    .unwrap()
                                    .call(&mut caller, params, results)?;

                                Ok(())
                            },
                        )
                    },
                )
            }
            ModuleKind::Reactor => {
                let instance = self.instantiate(&mut store, &module)?;

                if let Some(export) = instance.get_export(&mut store, "_initialize") {
                    if let Extern::Func(func) = export {
                        func.typed::<(), ()>(&store)
                            .and_then(|f| f.call(&mut store, ()).map_err(Into::into))
                            .context("calling the Reactor initialization function")?;
                    }
                }

                self.instance(store, module_name, instance)
            }
        }
    }

    /// Define automatic instantiations of a [`Module`] in this linker.
    ///
    /// This is the same as [`Linker::module`], except for async `Store`s.
    #[cfg(all(feature = "async", feature = "cranelift"))]
    #[cfg_attr(nightlydoc, doc(cfg(all(feature = "async", feature = "cranelift"))))]
    pub async fn module_async(
        &mut self,
        mut store: impl AsContextMut<Data = T>,
        module_name: &str,
        module: &Module,
    ) -> Result<&mut Self>
    where
        T: Send + 'static,
    {
        // NB: this is intended to function the same as `Linker::module`, they
        // should be kept in sync.
        assert!(
            Engine::same(&self.engine, store.as_context().engine()),
            "different engines for this linker and the store provided"
        );
        match ModuleKind::categorize(module)? {
            ModuleKind::Command => self.command(
                store,
                module_name,
                module,
                |store, func_ty, export_name, instance_pre| {
                    let upvars = Arc::new((instance_pre, export_name));
                    Func::new_async(
                        store,
                        func_ty.clone(),
                        move |mut caller, params, results| {
                            let upvars = upvars.clone();
                            Box::new(async move {
                                let (instance_pre, export_name) = &*upvars;
                                let instance = instance_pre.instantiate_async(&mut caller).await?;

                                instance
                                    .get_export(&mut caller, &export_name)
                                    .unwrap()
                                    .into_func()
                                    .unwrap()
                                    .call_async(&mut caller, params, results)
                                    .await?;
                                Ok(())
                            })
                        },
                    )
                },
            ),
            ModuleKind::Reactor => {
                let instance = self.instantiate_async(&mut store, &module).await?;

                if let Some(export) = instance.get_export(&mut store, "_initialize") {
                    if let Extern::Func(func) = export {
                        let func = func
                            .typed::<(), ()>(&store)
                            .context("loading the Reactor initialization function")?;
                        func.call_async(&mut store, ())
                            .await
                            .context("calling the Reactor initialization function")?;
                    }
                }

                self.instance(store, module_name, instance)
            }
        }
    }

Looks up an exported Func value by name.

Returns None if there was no export named name, or if there was but it wasn’t a function.

Panics

Panics if store does not own this instance.

Looks up an exported Func value by name and with its type.

This function is a convenience wrapper over Instance::get_func and Func::typed. For more information see the linked documentation.

Returns an error if name isn’t a function export or if the export’s type did not match Params or Results

Panics

Panics if store does not own this instance.

Looks up an exported Table value by name.

Returns None if there was no export named name, or if there was but it wasn’t a table.

Panics

Panics if store does not own this instance.

Looks up an exported Memory value by name.

Returns None if there was no export named name, or if there was but it wasn’t a memory.

Panics

Panics if store does not own this instance.

Looks up an exported SharedMemory value by name.

Returns None if there was no export named name, or if there was but it wasn’t a shared memory.

Panics

Panics if store does not own this instance.

Looks up an exported Global value by name.

Returns None if there was no export named name, or if there was but it wasn’t a global.

Panics

Panics if store does not own this instance.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

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

The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
Should always be Self
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.