Move Wasmtime for .NET to the Wasmtime repo.
This moves the Wasmtime for .NET implementation to the Wasmtime repo. Wasmtime for .NET is a binding of the Wasmtime API for use in .NET.
This commit is contained in:
87
crates/misc/dotnet/src/Externs/ExternFunction.cs
Normal file
87
crates/misc/dotnet/src/Externs/ExternFunction.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wasmtime.Exports;
|
||||
|
||||
namespace Wasmtime.Externs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an external (instantiated) WebAssembly function.
|
||||
/// </summary>
|
||||
public class ExternFunction
|
||||
{
|
||||
internal ExternFunction(FunctionExport export, IntPtr func)
|
||||
{
|
||||
_export = export;
|
||||
_func = func;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the WebAssembly function.
|
||||
/// </summary>
|
||||
public string Name => _export.Name;
|
||||
|
||||
/// <summary>
|
||||
/// The parameters of the WebAssembly function.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ValueKind> Parameters => _export.Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// The results of the WebAssembly function.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ValueKind> Results => _export.Results;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the WebAssembly function.
|
||||
/// </summary>
|
||||
/// <param name="arguments">The array of arguments to pass to the function.</param>
|
||||
/// <returns>
|
||||
/// Returns null if the function has no return value.
|
||||
/// Returns the value if the function returns a single value.
|
||||
/// Returns an array of values if the function returns more than one value.
|
||||
/// </returns>
|
||||
public object Invoke(params object[] arguments)
|
||||
{
|
||||
if (arguments.Length != Parameters.Count)
|
||||
{
|
||||
throw new WasmtimeException($"Argument mismatch when invoking function '{Name}': requires {Parameters.Count} but was given {arguments.Length}.");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
Interop.wasm_val_t* args = stackalloc Interop.wasm_val_t[Parameters.Count];
|
||||
Interop.wasm_val_t* results = stackalloc Interop.wasm_val_t[Results.Count];
|
||||
|
||||
for (int i = 0; i < arguments.Length; ++i)
|
||||
{
|
||||
args[i] = Interop.ToValue(arguments[i], Parameters[i]);
|
||||
}
|
||||
|
||||
var trap = Interop.wasm_func_call(_func, args, results);
|
||||
if (trap != IntPtr.Zero)
|
||||
{
|
||||
throw TrapException.FromOwnedTrap(trap);
|
||||
}
|
||||
|
||||
if (Results.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Results.Count == 1)
|
||||
{
|
||||
return Interop.ToObject(&results[0]);
|
||||
}
|
||||
|
||||
var ret = new object[Results.Count];
|
||||
for (int i = 0; i < Results.Count; ++i)
|
||||
{
|
||||
ret[i] = Interop.ToObject(&results[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
private FunctionExport _export;
|
||||
private IntPtr _func;
|
||||
}
|
||||
}
|
||||
62
crates/misc/dotnet/src/Externs/ExternGlobal.cs
Normal file
62
crates/misc/dotnet/src/Externs/ExternGlobal.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using Wasmtime.Exports;
|
||||
|
||||
namespace Wasmtime.Externs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an external (instantiated) WebAssembly global.
|
||||
/// </summary>
|
||||
public class ExternGlobal
|
||||
{
|
||||
internal ExternGlobal(GlobalExport export, IntPtr global)
|
||||
{
|
||||
_export = export;
|
||||
_global = global;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the WebAssembly global.
|
||||
/// </summary>
|
||||
public string Name => _export.Name;
|
||||
|
||||
/// <summary>
|
||||
/// The kind of value for the global variable.
|
||||
/// </summary>
|
||||
public ValueKind Kind => _export.Kind;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not the global variable is mutable.
|
||||
/// </summary>
|
||||
public bool IsMutable => _export.IsMutable;
|
||||
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var v = stackalloc Interop.wasm_val_t[1];
|
||||
Interop.wasm_global_get(_global, v);
|
||||
return Interop.ToObject(v);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!IsMutable)
|
||||
{
|
||||
throw new InvalidOperationException($"The value of global '{Name}' cannot be modified.");
|
||||
}
|
||||
|
||||
var v = Interop.ToValue(value, Kind);
|
||||
|
||||
unsafe
|
||||
{
|
||||
Interop.wasm_global_set(_global, &v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalExport _export;
|
||||
private IntPtr _global;
|
||||
}
|
||||
}
|
||||
245
crates/misc/dotnet/src/Externs/ExternMemory.cs
Normal file
245
crates/misc/dotnet/src/Externs/ExternMemory.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
using Wasmtime.Exports;
|
||||
|
||||
namespace Wasmtime.Externs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an external (instantiated) WebAssembly memory.
|
||||
/// </summary>
|
||||
public class ExternMemory
|
||||
{
|
||||
internal ExternMemory(MemoryExport export, IntPtr memory)
|
||||
{
|
||||
_export = export;
|
||||
_memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the WebAssembly memory.
|
||||
/// </summary>
|
||||
public string Name => _export.Name;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum memory size (in WebAssembly page units).
|
||||
/// </summary>
|
||||
public uint Minimum => _export.Minimum;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum memory size (in WebAssembly page units).
|
||||
/// </summary>
|
||||
public uint Maximum => _export.Maximum;
|
||||
|
||||
/// <summary>
|
||||
/// The span of the memory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The span may become invalid if the memory grows.
|
||||
///
|
||||
/// This may happen if the memory is explicitly requested to grow or
|
||||
/// grows as a result of WebAssembly execution.
|
||||
///
|
||||
/// Therefore, the returned Span should not be stored.
|
||||
/// </remarks>
|
||||
public unsafe Span<byte> Span
|
||||
{
|
||||
get
|
||||
{
|
||||
var data = Interop.wasm_memory_data(_memory);
|
||||
var size = Convert.ToInt32(Interop.wasm_memory_data_size(_memory).ToUInt32());
|
||||
return new Span<byte>(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a UTF-8 string from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <param name="length">The length of bytes to read.</param>
|
||||
/// <returns>Returns the string read from memory.</returns>
|
||||
public string ReadString(int address, int length)
|
||||
{
|
||||
return Encoding.UTF8.GetString(Span.Slice(address, length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a UTF-8 string at the given address.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The string to write.</param>
|
||||
/// <return>Returns the number of bytes written.</return>
|
||||
public int WriteString(int address, string value)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(value, Span.Slice(address));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the byte read from memory.</returns>
|
||||
public byte ReadByte(int address)
|
||||
{
|
||||
return Span[address];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a byte to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The byte to write.</param>
|
||||
public void WriteByte(int address, byte value)
|
||||
{
|
||||
Span[address] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a short from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the short read from memory.</returns>
|
||||
public short ReadInt16(int address)
|
||||
{
|
||||
return BinaryPrimitives.ReadInt16LittleEndian(Span.Slice(address, 2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a short to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The short to write.</param>
|
||||
public void WriteInt16(int address, short value)
|
||||
{
|
||||
BinaryPrimitives.WriteInt16LittleEndian(Span.Slice(address, 2), value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an int from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the int read from memory.</returns>
|
||||
public int ReadInt32(int address)
|
||||
{
|
||||
return BinaryPrimitives.ReadInt32LittleEndian(Span.Slice(address, 4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an int to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The int to write.</param>
|
||||
public void WriteInt32(int address, int value)
|
||||
{
|
||||
BinaryPrimitives.WriteInt32LittleEndian(Span.Slice(address, 4), value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a long from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the long read from memory.</returns>
|
||||
public long ReadInt64(int address)
|
||||
{
|
||||
return BinaryPrimitives.ReadInt64LittleEndian(Span.Slice(address, 8));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a long to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The long to write.</param>
|
||||
public void WriteInt64(int address, long value)
|
||||
{
|
||||
BinaryPrimitives.WriteInt64LittleEndian(Span.Slice(address, 8), value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an IntPtr from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the IntPtr read from memory.</returns>
|
||||
public IntPtr ReadIntPtr(int address)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
return (IntPtr)ReadInt32(address);
|
||||
}
|
||||
return (IntPtr)ReadInt64(address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an IntPtr to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The IntPtr to write.</param>
|
||||
public void WriteIntPtr(int address, IntPtr value)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
WriteInt32(address, value.ToInt32());
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteInt64(address, value.ToInt64());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a long from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the long read from memory.</returns>
|
||||
public float ReadSingle(int address)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var i = ReadInt32(address);
|
||||
return *((float*)&i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The single to write.</param>
|
||||
public void WriteSingle(int address, float value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
WriteInt32(address, *(int*)&value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double from memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to read from.</param>
|
||||
/// <returns>Returns the double read from memory.</returns>
|
||||
public double ReadDouble(int address)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var i = ReadInt64(address);
|
||||
return *((double*)&i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double to memory.
|
||||
/// </summary>
|
||||
/// <param name="address">The zero-based address to write to.</param>
|
||||
/// <param name="value">The double to write.</param>
|
||||
public void WriteDouble(int address, double value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
WriteInt64(address, *(long*)&value);
|
||||
}
|
||||
}
|
||||
|
||||
private MemoryExport _export;
|
||||
private IntPtr _memory;
|
||||
}
|
||||
}
|
||||
67
crates/misc/dotnet/src/Externs/Externs.cs
Normal file
67
crates/misc/dotnet/src/Externs/Externs.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wasmtime.Exports;
|
||||
|
||||
namespace Wasmtime.Externs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents external (instantiated) WebAssembly functions, globals, tables, and memories.
|
||||
/// </summary>
|
||||
public class Externs
|
||||
{
|
||||
internal Externs(Wasmtime.Exports.Exports exports, Interop.wasm_extern_vec_t externs)
|
||||
{
|
||||
var functions = new List<ExternFunction>();
|
||||
var globals = new List<ExternGlobal>();
|
||||
var memories = new List<ExternMemory>();
|
||||
|
||||
for (int i = 0; i < (int)externs.size; ++i)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var ext = externs.data[i];
|
||||
|
||||
switch (Interop.wasm_extern_kind(ext))
|
||||
{
|
||||
case Interop.wasm_externkind_t.WASM_EXTERN_FUNC:
|
||||
var function = new ExternFunction((FunctionExport)exports.All[i], Interop.wasm_extern_as_func(ext));
|
||||
functions.Add(function);
|
||||
break;
|
||||
|
||||
case Interop.wasm_externkind_t.WASM_EXTERN_GLOBAL:
|
||||
var global = new ExternGlobal((GlobalExport)exports.All[i], Interop.wasm_extern_as_global(ext));
|
||||
globals.Add(global);
|
||||
break;
|
||||
|
||||
case Interop.wasm_externkind_t.WASM_EXTERN_MEMORY:
|
||||
var memory = new ExternMemory((MemoryExport)exports.All[i], Interop.wasm_extern_as_memory(ext));
|
||||
memories.Add(memory);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported extern type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Functions = functions;
|
||||
Globals = globals;
|
||||
Memories = memories;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The extern functions from an instantiated WebAssembly module.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ExternFunction> Functions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The extern globals from an instantiated WebAssembly module.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ExternGlobal> Globals { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The extern memories from an instantiated WebAssembly module.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ExternMemory> Memories { get; private set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user