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; } }