using System;
using System.Collections.Generic;
using Wasmtime.Exports;
namespace Wasmtime.Externs
{
///
/// Represents an external (instantiated) WebAssembly function.
///
public class ExternFunction
{
internal ExternFunction(FunctionExport export, IntPtr func)
{
_export = export;
_func = func;
}
///
/// The name of the WebAssembly function.
///
public string Name => _export.Name;
///
/// The parameters of the WebAssembly function.
///
public IReadOnlyList Parameters => _export.Parameters;
///
/// The results of the WebAssembly function.
///
public IReadOnlyList Results => _export.Results;
///
/// Invokes the WebAssembly function.
///
/// The array of arguments to pass to the function.
///
/// 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.
///
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;
}
}