Skip to main content

Engines, Modules, Stores & Instances 😵

There are several stages to go through in the process of taking a .wasm file and loading it into executable code. This document explains the stages and the various objects involved at a high level.

Importing​

In Editor​

Wasmbox detects .wasm and .wat files in your project and imports them to create a WASM Asset and generated C# code.

At Runtime​

It is possible to load wasm or wat at runtime, without importing it in the editor, by using DynamicWasmAsset or even a custom implementation of IWasmAsset. All of these options produce something that can be used in the same way as an editor imported WASM Asset.

tip

Runtime loading does not generate wrapper code.

Loading​

At runtime a WASM Asset must be loaded and configured before it can be called. This process is quite complicated, but Wasmbox includes helpers such as the SimpleWasmMonoBehaviour which handle most of the steps for you.

  1. An EngineConfig configures how the code will be compiled.
  2. The EngineConfig is used to compile the WASM Asset into a LoadedModule.
  3. A Store is created from the EngineConfig, to store all state.
  4. A Linker is created from the EngineConfig, to set what the WASM code can access.
  5. Store, Linker & LoadedModule are used to create an Instance.
  6. Functions can be called on the Instance.

Glossary​

LoadedModule​

A LoadedModule compiles the WASM code stored in a WASM Asset into machine code that can be run on this machine. This process can take a lot of time (100ms or more) the first time it is done, but after that it is cached and should be nearly instantaneous.

tip

The editor importer can precompile WASM code in the editor, which significantly speeds up loading at runtime.

Store​

A WASM Instance has no state (i.e. memory), instead it is all contained within the Store. A Store may be shared between multiple Instances.

Linker​

By default WASM execution is completely "sandboxed", executing WASM code cannot access anything outside of the box. This makes it safe to run malicious code, and easy to ensure determinism. The Linker allows you to expose certain C# methods to WASM code, allowing it to call those methods. For example WASI features.

int Add(int a, int b)
{
return a + b;
}

// Allow WASM to call `Add` as `myfunctions::add`
linker.DefineFunction("myfunctions", "add", Add);

Instance​

An Instance is the final step which allows you to call WASM code.

var add = instance.GetFunction<int, int, int>("Add");
var result = add(1, 2);
Debug.Assert(result == 3);

Generated Code​

An Instance is a low level API that is often not very convenient to use directly. The Wasmbox editor importer can generate code which "wraps" an Instance and makes it much more convenient (and efficient) to use.

using (var wrapper = new GeneratedWrapper(instance, store))
{
var result = wrapper.Add(1, 2);
Debug.Assert(result == 3);
}