Skip to content

Commit c976fb2

Browse files
martindevanskpreisserpeterhuene
authored
Instance Get All Exports (#290)
* - Added methods to fetch all exports from an instance - Removed `wasmtime_instancetype_delete` (doesn't appear to be part of the c-api any more) * Added another import with no module name * Update tests/InstanceTests.cs Co-authored-by: Konstantin Preißer <[email protected]> * Apply suggestions from code review Co-authored-by: Peter Huene <[email protected]> * Removed unnecessary doc comment on private method --------- Co-authored-by: Konstantin Preißer <[email protected]> Co-authored-by: Peter Huene <[email protected]>
1 parent bd71441 commit c976fb2

File tree

2 files changed

+148
-3
lines changed

2 files changed

+148
-3
lines changed

src/Instance.cs

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Runtime.InteropServices;
34
using System.Text;
45

@@ -579,6 +580,101 @@ public Instance(Store store, Module module, params object[] imports)
579580
return _store.GetCachedExtern(ext.of.global);
580581
}
581582

583+
/// <summary>
584+
/// Get all exported functions
585+
/// </summary>
586+
/// <returns>An enumerable of functions exported from this instance</returns>
587+
public IEnumerable<(string Name, Function Function)> GetFunctions()
588+
{
589+
for (var i = 0; i < int.MaxValue; i++)
590+
{
591+
if (TryGetExtern(i, ExternKind.Func) is not var (name, @extern))
592+
{
593+
break;
594+
}
595+
596+
yield return (name, _store.GetCachedExtern(@extern.of.func));
597+
}
598+
599+
GC.KeepAlive(_store);
600+
}
601+
602+
/// <summary>
603+
/// Get all exported tables
604+
/// </summary>
605+
/// <returns>An enumerable of tables exported from this instance</returns>
606+
public IEnumerable<(string Name, Table Table)> GetTables()
607+
{
608+
for (var i = 0; i < int.MaxValue; i++)
609+
{
610+
if (TryGetExtern(i, ExternKind.Table) is not var (name, @extern))
611+
{
612+
break;
613+
}
614+
615+
yield return (name, new Table(_store, @extern.of.table));
616+
}
617+
618+
GC.KeepAlive(_store);
619+
}
620+
621+
/// <summary>
622+
/// Get all exported memories
623+
/// </summary>
624+
/// <returns>An enumerable of memories exported from this instance</returns>
625+
public IEnumerable<(string Name, Memory Memory)> GetMemories()
626+
{
627+
for (var i = 0; i < int.MaxValue; i++)
628+
{
629+
if (TryGetExtern(i, ExternKind.Memory) is not var (name, @extern))
630+
{
631+
break;
632+
}
633+
634+
yield return (name, _store.GetCachedExtern(@extern.of.memory));
635+
}
636+
637+
GC.KeepAlive(_store);
638+
}
639+
640+
/// <summary>
641+
/// Get all exported globals
642+
/// </summary>
643+
/// <returns>An enumerable of globals exported from this instance</returns>
644+
public IEnumerable<(string Name, Global Global)> GetGlobals()
645+
{
646+
for (var i = 0; i < int.MaxValue; i++)
647+
{
648+
if (TryGetExtern(i, ExternKind.Global) is not var (name, @extern))
649+
{
650+
break;
651+
}
652+
653+
yield return (name, _store.GetCachedExtern(@extern.of.global));
654+
}
655+
656+
GC.KeepAlive(_store);
657+
}
658+
659+
private (string name, Extern @extern)? TryGetExtern(int index, ExternKind? type = null)
660+
{
661+
unsafe
662+
{
663+
if (!Native.wasmtime_instance_export_nth(_store.Context.handle, instance, (UIntPtr)index, out var namePtr, out var nameLen, out var @extern))
664+
{
665+
return null;
666+
}
667+
668+
if (type != null && type.Value != @extern.kind)
669+
{
670+
return null;
671+
}
672+
673+
var name = Encoding.UTF8.GetString(namePtr, checked((int)nameLen));
674+
return (name, @extern);
675+
}
676+
}
677+
582678
private bool TryGetExtern(StoreContext context, string name, out Extern ext)
583679
{
584680
using var nameBytes = name.ToUTF8(stackalloc byte[Math.Min(64, name.Length * 2)]);
@@ -615,9 +711,6 @@ private static class Native
615711
[DllImport(Engine.LibraryName)]
616712
[return: MarshalAs(UnmanagedType.I1)]
617713
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);
618-
619-
[DllImport(Engine.LibraryName)]
620-
public static extern void wasmtime_instancetype_delete(IntPtr handle);
621714
}
622715

623716
private readonly Store _store;

tests/InstanceTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Linq;
3+
using FluentAssertions;
4+
using Xunit;
5+
6+
namespace Wasmtime.Tests
7+
{
8+
public class InstanceFixture
9+
: ModuleFixture
10+
{
11+
protected override string ModuleFileName => "hello.wat";
12+
}
13+
14+
public class InstanceTests
15+
: IClassFixture<InstanceFixture>, IDisposable
16+
{
17+
private Store Store { get; set; }
18+
19+
private Linker Linker { get; set; }
20+
21+
public InstanceTests(InstanceFixture fixture)
22+
{
23+
Fixture = fixture;
24+
Linker = new Linker(Fixture.Engine);
25+
Store = new Store(Fixture.Engine);
26+
27+
Linker.DefineFunction("env", "add", (int x, int y) => x + y);
28+
Linker.DefineFunction("env", "swap", (int x, int y) => (y, x));
29+
Linker.DefineFunction("", "hi", (int x, int y) => (y, x));
30+
31+
Linker.DefineFunction("", "hello", () => { });
32+
}
33+
34+
private InstanceFixture Fixture { get; }
35+
36+
[Fact]
37+
public void ItGetsExportedFunctions()
38+
{
39+
var instance = Linker.Instantiate(Store, Fixture.Module);
40+
41+
var results = instance.GetFunctions();
42+
43+
results.Single().Name.Should().Be("run");
44+
}
45+
46+
public void Dispose()
47+
{
48+
Store.Dispose();
49+
Linker.Dispose();
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)