Generated Code
When a *.wasm
or *.wat
file is imported the option Generate C# Wrapper Code
can be enabled to automatically generate a C# script which "wraps" the WASM module. This wrapper code handles most of the "low level" details of interacting with an instantiated WASM module.
The generated code should not be edited - it may be regenerated at any time which will overwrite any other changes made to the file.
Job Safety​
All autogenerated wrapper code is safe to use in the Unity Job System, this allows WASM execution to be moved off the main thread.
A WASM instance may only be accessed by one thread at a time (even for read-only operations), therefore the wrapper can only be used within one job at a time. The Unity Safety System is used to ensure this constraint is not violated.
For more information see this tutorial on multithreaded jobs.
WebAssembly System Interface (WASI)​
WebAssembly System Interface (WASI) is a set of APIs which allow access to system resources (such as the filesystem) in a tightly controlled way. If a WASM asset imports any functions which are part of the WASI spec, they will be marked in the inspector:
These functions must be defined in the Linker
before the module can be used. Wasmbox provides implementations of most WASI functions (see documentation here). Hovering over the WASI
marker in the editor will tell you which WASI implementation is required.
Optional Features​
The importer includes several optional features which slightly change how the code is generated.
Addressable Loading​
If this option is enabled the wrapper code will include a static CreateAsync
method which loads the asset (using the Unity Addressable Asset System), instantiates it and returns a wrapper object. Using this method no asset references are required in your script, instead everything to do with locating and loading the appropriate WasmAsset
is handled inside the CreateAsync
method.
For more information see this tutorial on addressable loading.
Trap Handling​
Certain events (e.g. running out of fuel) can interrupt execution of WASM code, this is called a "Trap". A trap is very similar to a C# exception - when it is triggered it immediately interrupts execution and "unwinds" the execution stack back out of the WASM engine. Code which calls into WASM must be aware that a trap can happen and be prepared to handle it.
The function wrappers which are generated can indicate a trap in one of two ways: Exceptions or Results.
Exception​
If Trap Handling
is set to Throw Exception
then a WASM trap will be converted into a C# TrapException
and thrown, this can be handled in the normal way in C# using try/catch
.
try
{
var value = wrapper.hello();
Debug.Log("WASM Result: " + value);
}
catch (TrapException ex)
{
Debug.LogError("WASM Trap: " + ex.Type);
}
Results​
If Trap handling
is set to Return Result
then every WASM function will return a result value which can be inspected to check if it represents a success or an error. This is faster than throwing an exception.
var result = wrapper.hello();
if (result.Type == ResultType.Ok)
{
var value = result.Value;
Debug.Log("WASM Result: " + value);
}
else
{
Debug.Log("WASM Trap: " + result.TrapCode);
}
Exported Functions​
Every function exported from the WASM will be wrapped in a C# method with the same name. If the name contains invalid characters (e.g. $wasm-function
) they will be replaced with underscores (e.g. _wasm_function
).
var result = wrapper._wasm_function(1, 2, 3);
Exported Globals​
Every global variable exported from the WASM will be wrapped in a C# property with the same name which returns a Global object. If the name contains invalid characters (e.g. $the-global
) they will be replaced with underscores (e.g. _the_global
). If the global is immutable the property will have a getter but not a setter.
var result = wrapper._a_global;
wrapper._a_global = result;
Exported Memory​
Every memory region exported from the WASM will be wrapped in a C# property with the same name which returns a Memory
object. If the name contains invalid characters (e.g. /memory\
) they will be replaced with underscores (e.g. _memory_
).
var integer = wrapper._memory_.ReadInt32(0);
wrapper._memory_.WriteInt32(0, integer + 1);
Exported Tables​
Every table exported from the WASM will be wrapped in a C# property with the same name which returns a Table
object. If the name contains invalid characters (e.g. this is a table
) they will be replaced with underscores (e.g. this_is_a_table
).
var size = wrapper.this_is_a_table.GetSize();