diff --git a/src/Instance.cs b/src/Instance.cs
index 7dadd4c..c82cf70 100644
--- a/src/Instance.cs
+++ b/src/Instance.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
@@ -579,6 +580,101 @@ public Instance(Store store, Module module, params object[] imports)
return _store.GetCachedExtern(ext.of.global);
}
+ ///
+ /// Get all exported functions
+ ///
+ /// An enumerable of functions exported from this instance
+ public IEnumerable<(string Name, Function Function)> GetFunctions()
+ {
+ for (var i = 0; i < int.MaxValue; i++)
+ {
+ if (TryGetExtern(i, ExternKind.Func) is not var (name, @extern))
+ {
+ break;
+ }
+
+ yield return (name, _store.GetCachedExtern(@extern.of.func));
+ }
+
+ GC.KeepAlive(_store);
+ }
+
+ ///
+ /// Get all exported tables
+ ///
+ /// An enumerable of tables exported from this instance
+ public IEnumerable<(string Name, Table Table)> GetTables()
+ {
+ for (var i = 0; i < int.MaxValue; i++)
+ {
+ if (TryGetExtern(i, ExternKind.Table) is not var (name, @extern))
+ {
+ break;
+ }
+
+ yield return (name, new Table(_store, @extern.of.table));
+ }
+
+ GC.KeepAlive(_store);
+ }
+
+ ///
+ /// Get all exported memories
+ ///
+ /// An enumerable of memories exported from this instance
+ public IEnumerable<(string Name, Memory Memory)> GetMemories()
+ {
+ for (var i = 0; i < int.MaxValue; i++)
+ {
+ if (TryGetExtern(i, ExternKind.Memory) is not var (name, @extern))
+ {
+ break;
+ }
+
+ yield return (name, _store.GetCachedExtern(@extern.of.memory));
+ }
+
+ GC.KeepAlive(_store);
+ }
+
+ ///
+ /// Get all exported globals
+ ///
+ /// An enumerable of globals exported from this instance
+ public IEnumerable<(string Name, Global Global)> GetGlobals()
+ {
+ for (var i = 0; i < int.MaxValue; i++)
+ {
+ if (TryGetExtern(i, ExternKind.Global) is not var (name, @extern))
+ {
+ break;
+ }
+
+ yield return (name, _store.GetCachedExtern(@extern.of.global));
+ }
+
+ GC.KeepAlive(_store);
+ }
+
+ private (string name, Extern @extern)? TryGetExtern(int index, ExternKind? type = null)
+ {
+ unsafe
+ {
+ if (!Native.wasmtime_instance_export_nth(_store.Context.handle, instance, (UIntPtr)index, out var namePtr, out var nameLen, out var @extern))
+ {
+ return null;
+ }
+
+ if (type != null && type.Value != @extern.kind)
+ {
+ return null;
+ }
+
+ var name = Encoding.UTF8.GetString(namePtr, checked((int)nameLen));
+ return (name, @extern);
+ }
+ }
+
private bool TryGetExtern(StoreContext context, string name, out Extern ext)
{
using var nameBytes = name.ToUTF8(stackalloc byte[Math.Min(64, name.Length * 2)]);
@@ -615,9 +711,6 @@ private static class Native
[DllImport(Engine.LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern unsafe bool wasmtime_instance_export_nth(IntPtr context, in ExternInstance instance, UIntPtr index, out byte* name, out UIntPtr len, out Extern ext);
-
- [DllImport(Engine.LibraryName)]
- public static extern void wasmtime_instancetype_delete(IntPtr handle);
}
private readonly Store _store;
diff --git a/tests/InstanceTests.cs b/tests/InstanceTests.cs
new file mode 100644
index 0000000..1ea71e9
--- /dev/null
+++ b/tests/InstanceTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Linq;
+using FluentAssertions;
+using Xunit;
+
+namespace Wasmtime.Tests
+{
+ public class InstanceFixture
+ : ModuleFixture
+ {
+ protected override string ModuleFileName => "hello.wat";
+ }
+
+ public class InstanceTests
+ : IClassFixture, IDisposable
+ {
+ private Store Store { get; set; }
+
+ private Linker Linker { get; set; }
+
+ public InstanceTests(InstanceFixture fixture)
+ {
+ Fixture = fixture;
+ Linker = new Linker(Fixture.Engine);
+ Store = new Store(Fixture.Engine);
+
+ Linker.DefineFunction("env", "add", (int x, int y) => x + y);
+ Linker.DefineFunction("env", "swap", (int x, int y) => (y, x));
+ Linker.DefineFunction("", "hi", (int x, int y) => (y, x));
+
+ Linker.DefineFunction("", "hello", () => { });
+ }
+
+ private InstanceFixture Fixture { get; }
+
+ [Fact]
+ public void ItGetsExportedFunctions()
+ {
+ var instance = Linker.Instantiate(Store, Fixture.Module);
+
+ var results = instance.GetFunctions();
+
+ results.Single().Name.Should().Be("run");
+ }
+
+ public void Dispose()
+ {
+ Store.Dispose();
+ Linker.Dispose();
+ }
+ }
+}