Implement WASI C API.

This commit implements an initial WASI C API that can be used to instantiate
and configure a WASI instance from C.

This also implements a `WasiBuilder` for the C# API enabling .NET hosts to bind
to Wasmtime's WASI implementation.
This commit is contained in:
Peter Huene
2020-02-07 11:24:26 -08:00
parent f8abe1169c
commit ae0b4090ce
28 changed files with 1303 additions and 268 deletions

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Dynamic;
using Wasmtime.Externs;
using Wasmtime.Bindings;
namespace Wasmtime
{
@@ -12,22 +13,23 @@ namespace Wasmtime
/// </summary>
public class Instance : DynamicObject, IDisposable
{
internal Instance(Module module, IHost host)
internal Instance(Module module, Wasi wasi = null, IHost host = null)
{
Host = host;
Module = module;
//Save the bindings to root the objects.
//Otherwise the GC may collect the delegates from ExternFunction for example.
_bindings = host.GetImportBindings(module);
var handles = _bindings.Select(b => b.Bind(module.Store, host)).ToList();
// Save the bindings to root the objects.
// Otherwise the GC may collect the callback delegates from FunctionHandles for example.
_bindings = Binding.GetImportBindings(module, wasi, host)
.Select(b => b.Bind(module.Store, host))
.ToArray();
unsafe
{
Handle = Interop.wasm_instance_new(
Module.Store.Handle,
Module.Handle,
handles.Select(h => ToExtern(h)).ToArray(),
_bindings.Select(h => ToExtern(h)).ToArray(),
out var trap);
if (trap != IntPtr.Zero)
@@ -41,12 +43,6 @@ namespace Wasmtime
throw new WasmtimeException($"Failed to instantiate module '{module.Name}'.");
}
// Dispose of all function handles (not needed at runtime)
foreach (var h in handles.Where(h => h is Interop.FunctionHandle))
{
h.Dispose();
}
Interop.wasm_instance_exports(Handle, out _externs);
Externs = new Wasmtime.Externs.Externs(Module.Exports, _externs);
@@ -71,17 +67,27 @@ namespace Wasmtime
public Wasmtime.Externs.Externs Externs { get; private set; }
/// <inheritdoc/>
public void Dispose()
public unsafe void Dispose()
{
if (!Handle.IsInvalid)
{
Handle.Dispose();
Handle.SetHandleAsInvalid();
}
if (_externs.size != UIntPtr.Zero)
if (!(_bindings is null))
{
foreach (var binding in _bindings)
{
binding.Dispose();
}
_bindings = null;
}
if (!(_externs.data is null))
{
Interop.wasm_extern_vec_delete(ref _externs);
_externs.size = UIntPtr.Zero;
_externs.data = null;
}
}
@@ -134,15 +140,18 @@ namespace Wasmtime
case Interop.MemoryHandle m:
return Interop.wasm_memory_as_extern(m);
case Interop.WasiExportHandle w:
return w.DangerousGetHandle();
default:
throw new NotSupportedException("Unexpected handle type.");
}
}
internal Interop.InstanceHandle Handle { get; private set; }
private SafeHandle[] _bindings;
private Interop.wasm_extern_vec_t _externs;
private Dictionary<string, ExternFunction> _functions;
private Dictionary<string, ExternGlobal> _globals;
private List<Bindings.Binding> _bindings;
}
}