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
.
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.
- An
EngineConfig
configures how the code will be compiled. - The
EngineConfig
is used to compile theWASM Asset
into aLoadedModule
. - A
Store
is created from theEngineConfig
, to store all state. - A
Linker
is created from theEngineConfig
, to set what the WASM code can access. Store
,Linker
&LoadedModule
are used to create anInstance
.- Functions can be called on the
Instance
.- Generated C# code can be used to make this easier.
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.
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);
}