diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ccda3bd5..3c05d1fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,19 +53,10 @@ jobs: if: matrix.config == 'release' run: dotnet run -c ${{ matrix.config }} --project benchmarks/simple/simple.csproj - name: Run examples + env: + EXAMPLES: externref funcref global hello linking memory table run: | - cd examples/hello - dotnet run - cd ../global - dotnet run - cd ../memory - dotnet run - cd ../table - dotnet run - cd ../externref - dotnet run - cd ../funcref - dotnet run + for e in $EXAMPLES; do cd examples/$e && dotnet run && cd ../..; done - name: Create package run: | cd src diff --git a/Directory.Build.props b/Directory.Build.props index 33ec2c72..e2dbd9ed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ true - 0.21.0 + 0.22.0 $(WasmtimeVersion)-preview1-dev $(WasmtimeVersion)-preview1 diff --git a/README.md b/README.md index 48481fd8..445eb53b 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,10 @@ ## Installation -You can add a package reference with the [.NET Core SDK](https://dotnet.microsoft.com/): +You can add a package reference with the [.NET SDK](https://dotnet.microsoft.com/): ```text -$ dotnet add package --version 0.21.0-preview1 wasmtime +$ dotnet add package --version 0.22.0-preview1 wasmtime ``` _Note that the `--version` option is required because the package is currently prerelease._ @@ -54,7 +54,7 @@ $ dotnet new console Next, add a reference to the [Wasmtime package](https://www.nuget.org/packages/Wasmtime): ``` -$ dotnet add package --version 0.21.0-preview1 wasmtime +$ dotnet add package --version 0.22.0-preview1 wasmtime ``` Replace the contents of `Program.cs` with the following code: diff --git a/benchmarks/simple/simple.csproj b/benchmarks/simple/simple.csproj index da3d0d7a..d9f7ceac 100644 --- a/benchmarks/simple/simple.csproj +++ b/benchmarks/simple/simple.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/docs/articles/intro.md b/docs/articles/intro.md index f07e4337..e98aee63 100644 --- a/docs/articles/intro.md +++ b/docs/articles/intro.md @@ -4,7 +4,7 @@ The [.NET embedding of Wasmtime](https://github.com/bytecodealliance/wasmtime-dotnet) enables .NET developers to easily instantiate and execute WebAssembly modules using Wasmtime. -For this tutorial, we will create a WebAssembly module and use that WebAssembly module from a .NET Core 3.1 application. +For this tutorial, we will create a WebAssembly module and use that WebAssembly module from a .NET 5 application. # A simple WebAssembly module @@ -23,13 +23,13 @@ This module simply imports a `hello` function from the host and exports a `run` # Using the WebAssembly module from .NET -## Installing a .NET Core 3.0 SDK +## Installing a .NET 5 SDK -Install a [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1) for your platform if you haven't already. +Install a [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) for your platform if you haven't already. This will add a `dotnet` command to your PATH. -## Creating the .NET Core project +## Creating the .NET project The .NET program will be a simple console application, so create a new console project with `dotnet new`: @@ -44,7 +44,7 @@ dotnet new console To use the .NET embedding of Wasmtime from the project, we need to add a reference to the [Wasmtime NuGet package](https://www.nuget.org/packages/Wasmtime): ```text -dotnet add package --version 0.21.0-preview1 wasmtime +dotnet add package --version 0.22.0-preview1 wasmtime ``` _Note that the `--version` option is required because the package is currently prerelease._ @@ -100,7 +100,7 @@ Use `dotnet build` to build the .NET application: dotnet build ``` -This will create a `tutorial` (or `tutorial.exe` on Windows) executable in the `bin/Debug/netcoreapp3.1` directory that implements the .NET Core application. +This will create a `tutorial` (or `tutorial.exe` on Windows) executable in the `bin/Debug/net5.0` directory that implements the .NET application. ## Running the .NET application diff --git a/examples/externref/externref.csproj b/examples/externref/externref.csproj index fcb4b054..d92d9915 100644 --- a/examples/externref/externref.csproj +++ b/examples/externref/externref.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/examples/funcref/funcref.csproj b/examples/funcref/funcref.csproj index fcb4b054..d92d9915 100644 --- a/examples/funcref/funcref.csproj +++ b/examples/funcref/funcref.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/examples/global/Program.cs b/examples/global/Program.cs index 44c28137..2952f1e2 100644 --- a/examples/global/Program.cs +++ b/examples/global/Program.cs @@ -16,7 +16,8 @@ static void Main(string[] args) using var function = host.DefineFunction( "", "print_global", - () => { + () => + { Console.WriteLine($"The value of the global is: {global.Value}."); } ); diff --git a/examples/global/global.csproj b/examples/global/global.csproj index fcb4b054..d92d9915 100644 --- a/examples/global/global.csproj +++ b/examples/global/global.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/examples/hello/hello.csproj b/examples/hello/hello.csproj index fcb4b054..d92d9915 100644 --- a/examples/hello/hello.csproj +++ b/examples/hello/hello.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/examples/linking/Program.cs b/examples/linking/Program.cs new file mode 100644 index 00000000..15ed93e7 --- /dev/null +++ b/examples/linking/Program.cs @@ -0,0 +1,31 @@ +using System; +using Wasmtime; + +namespace Example +{ + class Program + { + static void Main(string[] args) + { + using var engine = new EngineBuilder().WithModuleLinking(true).Build(); + using var module = Module.FromTextFile(engine, "name.wat"); + using var program = Module.FromTextFile(engine, "program.wat"); + + using var store = new Store(engine); + using var host = new Host(store); + + using var memory = host.DefineMemory("", "mem"); + + host.DefineInstance("", "inst", module.Instantiate(store, memory)); + + host.DefineFunction("", "print", (Caller caller, int addr, int len) => + { + Console.WriteLine(caller.GetMemory("mem").ReadString(addr, len)); + }); + + using dynamic instance = host.Instantiate(program); + + instance.run(); + } + } +} diff --git a/examples/linking/linking.csproj b/examples/linking/linking.csproj new file mode 100644 index 00000000..d92d9915 --- /dev/null +++ b/examples/linking/linking.csproj @@ -0,0 +1,12 @@ + + + + Exe + net5.0 + + + + + + + diff --git a/examples/linking/name.wat b/examples/linking/name.wat new file mode 100644 index 00000000..eef01ab6 --- /dev/null +++ b/examples/linking/name.wat @@ -0,0 +1,21 @@ +(module + (import "" "mem" (memory 1)) + (func $name (export "write") (param i32) (result i32) + local.get 0 + i32.const 119 ;;; w + i32.store offset=0 align=1 + local.get 0 + i32.const 111 ;;; o + i32.store offset=1 align=1 + local.get 0 + i32.const 114 ;;; r + i32.store offset=2 align=1 + local.get 0 + i32.const 108 ;;; l + i32.store offset=3 align=1 + local.get 0 + i32.const 100 ;;; d + i32.store offset=4 align=1 + i32.const 5 + ) +) diff --git a/examples/linking/program.wat b/examples/linking/program.wat new file mode 100644 index 00000000..ebf4c544 --- /dev/null +++ b/examples/linking/program.wat @@ -0,0 +1,21 @@ +(module + (import "" "print" (func $print (param i32 i32))) + (import "" "inst" (instance $inst (export "write" (func $write (param i32) (result i32))))) + (import "" "mem" (memory 1)) + (export "mem" (memory 0)) + (func (export "run") (local i32) + i32.const 6 + call $inst.$write + i32.const 6 + i32.add + local.tee 0 + i32.const 33 ;;; ! + i32.store align=1 + i32.const 0 + local.get 0 + i32.const 1 + i32.add + call $print + ) + (data (i32.const 0) "Hello ") +) diff --git a/examples/memory/Program.cs b/examples/memory/Program.cs index dd3e0915..57e3daef 100644 --- a/examples/memory/Program.cs +++ b/examples/memory/Program.cs @@ -14,7 +14,8 @@ static void Main(string[] args) using var function = host.DefineFunction( "", "log", - (Caller caller, int address, int length) => { + (Caller caller, int address, int length) => + { var message = caller.GetMemory("mem").ReadString(address, length); Console.WriteLine($"Message from WebAssembly: {message}"); } diff --git a/examples/memory/memory.csproj b/examples/memory/memory.csproj index fcb4b054..d92d9915 100644 --- a/examples/memory/memory.csproj +++ b/examples/memory/memory.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/examples/table/table.csproj b/examples/table/table.csproj index fcb4b054..d92d9915 100644 --- a/examples/table/table.csproj +++ b/examples/table/table.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/src/EngineBuilder.cs b/src/EngineBuilder.cs index 7510b5ce..b2eb004f 100644 --- a/src/EngineBuilder.cs +++ b/src/EngineBuilder.cs @@ -178,6 +178,12 @@ public EngineBuilder WithOptimizationLevel(OptimizationLevel level) return this; } + public EngineBuilder WithModuleLinking(bool enable) + { + _enableModuleLinking = enable; + return this; + } + /// /// Builds the instance. /// @@ -216,6 +222,11 @@ public Engine Build() Interop.wasmtime_config_wasm_multi_value_set(config, _enableMultiValue.Value); } + if (_enableModuleLinking.HasValue) + { + Interop.wasmtime_config_wasm_module_linking_set(config, _enableModuleLinking.Value); + } + if (_strategy.HasValue) { Interop.wasmtime_config_strategy_set(config, _strategy.Value); @@ -240,6 +251,7 @@ public Engine Build() private bool? _enableSIMD; private bool? _enableBulkMemory; private bool? _enableMultiValue; + private bool? _enableModuleLinking; private Interop.wasmtime_strategy_t? _strategy; private bool? _enableCraneliftDebugVerifier; private Interop.wasmtime_opt_level_t? _optLevel; diff --git a/src/Exports/Export.cs b/src/Exports/Export.cs index 047ad702..13e6c514 100644 --- a/src/Exports/Export.cs +++ b/src/Exports/Export.cs @@ -4,7 +4,7 @@ namespace Wasmtime.Exports { /// - /// Represents an export of a WebAssembly module. + /// Represents an export of a WebAssembly module or instance. /// public abstract class Export { @@ -13,7 +13,14 @@ internal Export(IntPtr exportType) unsafe { var name = Interop.wasm_exporttype_name(exportType); - Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size); + if (name->size == UIntPtr.Zero) + { + Name = String.Empty; + } + else + { + Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size); + } } } diff --git a/src/Exports/Exports.cs b/src/Exports/Exports.cs index 52d50c3c..397d72e2 100644 --- a/src/Exports/Exports.cs +++ b/src/Exports/Exports.cs @@ -4,94 +4,110 @@ namespace Wasmtime.Exports { /// - /// Represents the exports of a WebAssembly module. + /// Represents the exports of a WebAssembly module or instance. /// public class Exports { - internal Exports(Module module) + internal Exports(Interop.wasm_exporttype_vec_t exports) { - Interop.wasm_exporttype_vec_t exports; - Interop.wasm_module_exports(module.Handle, out exports); + var all = new List((int)exports.size); + var functions = new List(); + var globals = new List(); + var tables = new List(); + var memories = new List(); + var instances = new List(); + var modules = new List(); - try + for (int i = 0; i < (int)exports.size; ++i) { - var all = new List((int)exports.size); - var functions = new List(); - var globals = new List(); - var tables = new List(); - var memories = new List(); - - for (int i = 0; i < (int)exports.size; ++i) + unsafe { - unsafe + var exportType = exports.data[i]; + var externType = Interop.wasm_exporttype_type(exportType); + + switch (Interop.wasm_externtype_kind(externType)) { - var exportType = exports.data[i]; - var externType = Interop.wasm_exporttype_type(exportType); - - switch (Interop.wasm_externtype_kind(externType)) - { - case Interop.wasm_externkind_t.WASM_EXTERN_FUNC: - var function = new FunctionExport(exportType, externType); - functions.Add(function); - all.Add(function); - break; - - case Interop.wasm_externkind_t.WASM_EXTERN_GLOBAL: - var global = new GlobalExport(exportType, externType); - globals.Add(global); - all.Add(global); - break; - - case Interop.wasm_externkind_t.WASM_EXTERN_TABLE: - var table = new TableExport(exportType, externType); - tables.Add(table); - all.Add(table); - break; - - case Interop.wasm_externkind_t.WASM_EXTERN_MEMORY: - var memory = new MemoryExport(exportType, externType); - memories.Add(memory); - all.Add(memory); - break; - - default: - throw new NotSupportedException("Unsupported export extern type."); - } + case Interop.wasm_externkind_t.WASM_EXTERN_FUNC: + var function = new FunctionExport(exportType, externType); + functions.Add(function); + all.Add(function); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_GLOBAL: + var global = new GlobalExport(exportType, externType); + globals.Add(global); + all.Add(global); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_TABLE: + var table = new TableExport(exportType, externType); + tables.Add(table); + all.Add(table); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_MEMORY: + var memory = new MemoryExport(exportType, externType); + memories.Add(memory); + all.Add(memory); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_INSTANCE: + var instance = new InstanceExport(exportType, externType); + instances.Add(instance); + all.Add(instance); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_MODULE: + var module = new ModuleExport(exportType, externType); + modules.Add(module); + all.Add(module); + break; + + default: + throw new NotSupportedException("Unsupported export extern type."); } } - - Functions = functions; - Globals = globals; - Tables = tables; - Memories = memories; - All = all; - } - finally - { - Interop.wasm_exporttype_vec_delete(ref exports); } + + Functions = functions; + Globals = globals; + Tables = tables; + Memories = memories; + Instances = instances; + Modules = modules; + All = all; } /// - /// The exported functions of a WebAssembly module. + /// The exported functions of a WebAssembly module or instance. /// public IReadOnlyList Functions { get; private set; } /// - /// The exported globals of a WebAssembly module. + /// The exported globals of a WebAssembly module or instance. /// public IReadOnlyList Globals { get; private set; } /// - /// The exported tables of a WebAssembly module. + /// The exported tables of a WebAssembly module or instance. /// public IReadOnlyList Tables { get; private set; } /// - /// The exported memories of a WebAssembly module. + /// The exported memories of a WebAssembly module or instance. /// public IReadOnlyList Memories { get; private set; } + /// + /// The exported instances of a WebAssembly module or instance. + /// + public IReadOnlyList Instances { get; private set; } + + /// + /// The exported modules of a WebAssembly module or instance. + /// + public IReadOnlyList Modules { get; private set; } + internal List All { get; private set; } } } diff --git a/src/Exports/FunctionExport.cs b/src/Exports/FunctionExport.cs index 1b57c65c..e9ec17a2 100644 --- a/src/Exports/FunctionExport.cs +++ b/src/Exports/FunctionExport.cs @@ -5,7 +5,7 @@ namespace Wasmtime.Exports { /// - /// Represents a function exported from a WebAssembly module. + /// Represents a function exported from a WebAssembly module or instance. /// public class FunctionExport : Export { diff --git a/src/Exports/GlobalExport.cs b/src/Exports/GlobalExport.cs index 3dc76be5..6c4fb27a 100644 --- a/src/Exports/GlobalExport.cs +++ b/src/Exports/GlobalExport.cs @@ -4,7 +4,7 @@ namespace Wasmtime.Exports { /// - /// Represents a global variable exported from a WebAssembly module. + /// Represents a global variable exported from a WebAssembly module or instance. /// public class GlobalExport : Export { diff --git a/src/Exports/InstanceExport.cs b/src/Exports/InstanceExport.cs new file mode 100644 index 00000000..ab45309a --- /dev/null +++ b/src/Exports/InstanceExport.cs @@ -0,0 +1,35 @@ +using System; +using System.Diagnostics; + +namespace Wasmtime.Exports +{ + /// + /// Represents an instance exported from a WebAssembly module or instance. + /// + public class InstanceExport : Export + { + internal InstanceExport(IntPtr exportType, IntPtr externType) : base(exportType) + { + Debug.Assert(Interop.wasm_externtype_kind(externType) == Interop.wasm_externkind_t.WASM_EXTERN_INSTANCE); + + var instanceType = Interop.wasm_externtype_as_instancetype_const(externType); + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_instancetype_exports(instanceType, out exports); + + try + { + Exports = new Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } + } + + /// + /// The exports of the instance. + /// + public Exports Exports { get; private set; } + } +} diff --git a/src/Exports/MemoryExport.cs b/src/Exports/MemoryExport.cs index f5f200e3..419273c2 100644 --- a/src/Exports/MemoryExport.cs +++ b/src/Exports/MemoryExport.cs @@ -4,7 +4,7 @@ namespace Wasmtime.Exports { /// - /// Represents a memory exported from a WebAssembly module. + /// Represents a memory exported from a WebAssembly module or instance. /// public class MemoryExport : Export { diff --git a/src/Exports/ModuleExport.cs b/src/Exports/ModuleExport.cs new file mode 100644 index 00000000..733698d3 --- /dev/null +++ b/src/Exports/ModuleExport.cs @@ -0,0 +1,52 @@ +using System; +using System.Diagnostics; + +namespace Wasmtime.Exports +{ + /// + /// Represents a module exported from a WebAssembly module or instance. + /// + public class ModuleExport : Export + { + internal ModuleExport(IntPtr exportType, IntPtr externType) : base(exportType) + { + Debug.Assert(Interop.wasm_externtype_kind(externType) == Interop.wasm_externkind_t.WASM_EXTERN_MODULE); + + var moduleType = Interop.wasm_externtype_as_moduletype_const(externType); + + Interop.wasm_importtype_vec_t imports; + Interop.wasm_moduletype_imports(moduleType, out imports); + + try + { + Imports = new Imports.Imports(imports); + } + finally + { + Interop.wasm_importtype_vec_delete(ref imports); + } + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_moduletype_exports(moduleType, out exports); + + try + { + Exports = new Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } + } + + /// + /// The imports of the module. + /// + public Imports.Imports Imports { get; private set; } + + /// + /// The exports of the module. + /// + public Exports Exports { get; private set; } + } +} diff --git a/src/Exports/TableExport.cs b/src/Exports/TableExport.cs index 1643aee6..e708e49b 100644 --- a/src/Exports/TableExport.cs +++ b/src/Exports/TableExport.cs @@ -4,7 +4,7 @@ namespace Wasmtime.Exports { /// - /// Represents a table exported from a WebAssembly module. + /// Represents a table exported from a WebAssembly module or instance. /// public class TableExport : Export { diff --git a/src/Externs/ExternFunction.cs b/src/Externs/ExternFunction.cs index fc84f140..1dd89d3f 100644 --- a/src/Externs/ExternFunction.cs +++ b/src/Externs/ExternFunction.cs @@ -5,9 +5,9 @@ namespace Wasmtime.Externs { /// - /// Represents an external (instantiated) WebAssembly function. + /// Represents an external WebAssembly function. /// - public class ExternFunction + public class ExternFunction : IImportable { internal ExternFunction(FunctionExport export, IntPtr func) { @@ -59,6 +59,11 @@ internal ExternFunction(FunctionExport export, IntPtr func) return Function.Invoke(_func, Parameters, Results, arguments); } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_func_as_extern(_func); + } + private FunctionExport _export; private IntPtr _func; } diff --git a/src/Externs/ExternGlobal.cs b/src/Externs/ExternGlobal.cs index 8918dd14..e5202afc 100644 --- a/src/Externs/ExternGlobal.cs +++ b/src/Externs/ExternGlobal.cs @@ -4,9 +4,9 @@ namespace Wasmtime.Externs { /// - /// Represents an external (instantiated) WebAssembly global. + /// Represents an external WebAssembly global. /// - public class ExternGlobal + public class ExternGlobal : IImportable { internal ExternGlobal(GlobalExport export, IntPtr global) { @@ -56,6 +56,11 @@ public object? Value } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_global_as_extern(_global); + } + private GlobalExport _export; private IntPtr _global; } diff --git a/src/Externs/ExternInstance.cs b/src/Externs/ExternInstance.cs new file mode 100644 index 00000000..385d7a89 --- /dev/null +++ b/src/Externs/ExternInstance.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using Wasmtime.Exports; + +namespace Wasmtime.Externs +{ + /// + /// Represents an external WebAssembly module instance. + /// + public class ExternInstance : DynamicObject, IDisposable, IImportable + { + internal ExternInstance(InstanceExport export, IntPtr instance) + { + _export = export; + _instance = instance; + _externs = new Externs(_export.Exports, _instance); + _functions = Functions.ToDictionary(f => f.Name); + _globals = Globals.ToDictionary(g => g.Name); + } + + /// + /// The name of the WebAssembly instance. + /// + public string Name => _export.Name; + + /// + /// The exported functions of the instance. + /// + public IReadOnlyList Functions => _externs.Functions; + + /// + /// The exported globals of the instance. + /// + public IReadOnlyList Globals => _externs.Globals; + + /// + /// The exported tables of the instance. + /// + public IReadOnlyList Tables => _externs.Tables; + + /// + /// The exported memories of the instance. + /// + public IReadOnlyList Memories => _externs.Memories; + + /// + /// The exported instances of the instance. + /// + public IReadOnlyList Instances => _externs.Instances; + + /// + /// The exported modules of the instance. + /// + public IReadOnlyList Modules => _externs.Modules; + + /// + public override bool TryGetMember(GetMemberBinder binder, out object? result) + { + if (_globals.TryGetValue(binder.Name, out var global)) + { + result = global.Value; + return true; + } + result = null; + return false; + } + + /// + public override bool TrySetMember(SetMemberBinder binder, object value) + { + if (_globals.TryGetValue(binder.Name, out var global)) + { + global.Value = value; + return true; + } + return false; + } + + /// + public override bool TryInvokeMember(InvokeMemberBinder binder, object?[] args, out object? result) + { + if (!_functions.TryGetValue(binder.Name, out var func)) + { + result = null; + return false; + } + + result = func.Invoke(args); + return true; + } + + /// + public unsafe void Dispose() + { + foreach (var instance in Instances) + { + instance.Dispose(); + } + + if (!(_externs is null)) + { + _externs.Dispose(); + } + } + + IntPtr IImportable.GetHandle() + { + return Interop.wasm_instance_as_extern(_instance); + } + + private InstanceExport _export; + private IntPtr _instance; + private Externs _externs; + private Dictionary _functions; + private Dictionary _globals; + } +} diff --git a/src/Externs/ExternMemory.cs b/src/Externs/ExternMemory.cs index 320d8d4d..eccd8296 100644 --- a/src/Externs/ExternMemory.cs +++ b/src/Externs/ExternMemory.cs @@ -4,9 +4,9 @@ namespace Wasmtime.Externs { /// - /// Represents an external (instantiated) WebAssembly memory. + /// Represents an external WebAssembly memory. /// - public class ExternMemory : MemoryBase + public class ExternMemory : MemoryBase, IImportable { internal ExternMemory(MemoryExport export, IntPtr memory) { @@ -14,6 +14,11 @@ internal ExternMemory(MemoryExport export, IntPtr memory) _memory = memory; } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_memory_as_extern(_memory); + } + /// /// The name of the WebAssembly memory. /// diff --git a/src/Externs/ExternModule.cs b/src/Externs/ExternModule.cs new file mode 100644 index 00000000..9ee4dbea --- /dev/null +++ b/src/Externs/ExternModule.cs @@ -0,0 +1,110 @@ +using System; +using Wasmtime.Exports; + +namespace Wasmtime.Externs +{ + /// + /// Represents an external WebAssembly module. + /// + public class ExternModule : IImportable + { + /// + /// The imports of the module. + /// + public Wasmtime.Imports.Imports Imports { get; private set; } + + /// + /// The exports of the module. + /// + /// + public Wasmtime.Exports.Exports Exports { get; private set; } + + /// + /// Instantiates the module given a set of imports. + /// + /// The store to associate with the instance. + /// The imports to use for the instantiations. + /// Returns a new . + public Instance Instantiate(Store store, params IImportable[] imports) + { + if (store is null) + { + throw new ArgumentNullException(nameof(store)); + } + + if (imports is null) + { + throw new ArgumentNullException(nameof(imports)); + } + + unsafe + { + IntPtr* handles = stackalloc IntPtr[imports.Length]; + + for (int i = 0; i < imports.Length; ++i) + { + unsafe + { + handles[i] = imports[i].GetHandle(); + } + } + + var error = Interop.wasmtime_instance_new(store.Handle, _module, handles, (UIntPtr)imports.Length, out var instance, out var trap); + + if (error != IntPtr.Zero) + { + throw WasmtimeException.FromOwnedError(error); + } + if (trap != IntPtr.Zero) + { + throw TrapException.FromOwnedTrap(trap); + } + + return new Instance(instance, _module); + } + } + + internal ExternModule(ModuleExport export, IntPtr module) + { + _export = export; + _module = module; + + Interop.wasm_importtype_vec_t imports; + Interop.wasm_module_imports(_module, out imports); + + try + { + Imports = new Wasmtime.Imports.Imports(imports); + } + finally + { + Interop.wasm_importtype_vec_delete(ref imports); + } + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_module_exports(_module, out exports); + + try + { + Exports = new Wasmtime.Exports.Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } + } + + IntPtr IImportable.GetHandle() + { + return Interop.wasm_module_as_extern(_module); + } + + /// + /// The name of the WebAssembly module. + /// + public string Name => _export.Name; + + private ModuleExport _export; + private IntPtr _module; + } +} diff --git a/src/Externs/ExternTable.cs b/src/Externs/ExternTable.cs index 8d7543d2..4e2d891b 100644 --- a/src/Externs/ExternTable.cs +++ b/src/Externs/ExternTable.cs @@ -4,9 +4,9 @@ namespace Wasmtime.Externs { /// - /// Represents an external (instantiated) WebAssembly table. + /// Represents an external WebAssembly table. /// - public class ExternTable + public class ExternTable : IImportable { internal ExternTable(TableExport export, IntPtr table) { @@ -14,6 +14,11 @@ internal ExternTable(TableExport export, IntPtr table) _table = table; } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_table_as_extern(_table); + } + /// /// The name of the WebAssembly table. /// diff --git a/src/Externs/Externs.cs b/src/Externs/Externs.cs index e6500683..e72db520 100644 --- a/src/Externs/Externs.cs +++ b/src/Externs/Externs.cs @@ -5,22 +5,26 @@ namespace Wasmtime.Externs { /// - /// Represents external (instantiated) WebAssembly functions, globals, tables, and memories. + /// Represents external WebAssembly functions, globals, tables, and memories. /// - public class Externs + internal class Externs : IDisposable { - internal Externs(Wasmtime.Exports.Exports exports, Interop.wasm_extern_vec_t externs) + internal Externs(Wasmtime.Exports.Exports exports, IntPtr instanceHandle) { var functions = new List(); var globals = new List(); var tables = new List(); var memories = new List(); + var instances = new List(); + var modules = new List(); - for (int i = 0; i < (int)externs.size; ++i) + Interop.wasm_instance_exports(instanceHandle, out _externs); + + for (int i = 0; i < (int)_externs.size; ++i) { unsafe { - var ext = externs.data[i]; + var ext = _externs.data[i]; switch (Interop.wasm_extern_kind(ext)) { @@ -44,6 +48,16 @@ internal Externs(Wasmtime.Exports.Exports exports, Interop.wasm_extern_vec_t ext memories.Add(memory); break; + case Interop.wasm_externkind_t.WASM_EXTERN_INSTANCE: + var instance = new ExternInstance((InstanceExport)exports.All[i], Interop.wasm_extern_as_instance(ext)); + instances.Add(instance); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_MODULE: + var module = new ExternModule((ModuleExport)exports.All[i], Interop.wasm_extern_as_module(ext)); + modules.Add(module); + break; + default: throw new NotSupportedException("Unsupported extern type."); } @@ -54,6 +68,8 @@ internal Externs(Wasmtime.Exports.Exports exports, Interop.wasm_extern_vec_t ext Globals = globals; Tables = tables; Memories = memories; + Instances = instances; + Modules = modules; } /// @@ -75,5 +91,32 @@ internal Externs(Wasmtime.Exports.Exports exports, Interop.wasm_extern_vec_t ext /// The extern memories from an instantiated WebAssembly module. /// public IReadOnlyList Memories { get; private set; } + + /// + /// The extern instances from an instantiated WebAssembly module. + /// + public IReadOnlyList Instances { get; private set; } + + /// + /// The extern modules from an instantiated WebAssembly module. + /// + public IReadOnlyList Modules { get; private set; } + + /// + public unsafe void Dispose() + { + foreach (var instance in Instances) + { + instance.Dispose(); + } + + if (!(_externs.data is null)) + { + Interop.wasm_extern_vec_delete(ref _externs); + _externs.data = null; + } + } + + private Interop.wasm_extern_vec_t _externs; } } diff --git a/src/Function.cs b/src/Function.cs index 9f819084..f83eb08a 100644 --- a/src/Function.cs +++ b/src/Function.cs @@ -11,7 +11,7 @@ namespace Wasmtime /// /// Represents a WebAsssembly function. /// - public class Function : IDisposable + public class Function : IDisposable, IImportable { /// /// Creates a function given a callback. @@ -594,6 +594,11 @@ public void Dispose() } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_func_as_extern(Handle.DangerousGetHandle()); + } + internal static object? Invoke(IntPtr func, IReadOnlyList funcParameters, IReadOnlyList funcResults, ReadOnlySpan arguments) { if (arguments.Length != funcParameters.Count) diff --git a/src/Global.cs b/src/Global.cs index 1840edc4..5b0b0b7a 100644 --- a/src/Global.cs +++ b/src/Global.cs @@ -6,7 +6,7 @@ namespace Wasmtime /// /// Represents a constant WebAssembly global value. /// - public class Global : IDisposable + public class Global : IDisposable, IImportable { /// /// The value of the global. @@ -43,6 +43,11 @@ public void Dispose() } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_global_as_extern(Handle.DangerousGetHandle()); + } + internal Global(Interop.StoreHandle store, T initialValue) { if (!Interop.TryGetValueKind(typeof(T), out var kind)) diff --git a/src/Host.cs b/src/Host.cs index 4d179e3a..67ff47d7 100644 --- a/src/Host.cs +++ b/src/Host.cs @@ -522,7 +522,7 @@ public Global DefineGlobal(string moduleName, string name, T initialValue) } var global = new Global(_store, initialValue); - var ex = Define(moduleName, name, Interop.wasm_global_as_extern(global.Handle)); + var ex = Define(moduleName, name, Interop.wasm_global_as_extern(global.Handle.DangerousGetHandle())); if (ex != null) { @@ -556,7 +556,7 @@ public MutableGlobal DefineMutableGlobal(string moduleName, string name, T } var global = new MutableGlobal(_store, initialValue); - var ex = Define(moduleName, name, Interop.wasm_global_as_extern(global.Handle)); + var ex = Define(moduleName, name, Interop.wasm_global_as_extern(global.Handle.DangerousGetHandle())); if (ex != null) { @@ -590,7 +590,7 @@ public Memory DefineMemory(string moduleName, string name, uint minimum = 1, uin } var memory = new Memory(_store, minimum, maximum); - var ex = Define(moduleName, name, Interop.wasm_memory_as_extern(memory.Handle)); + var ex = Define(moduleName, name, Interop.wasm_memory_as_extern(memory.Handle.DangerousGetHandle())); if (ex != null) { @@ -626,7 +626,7 @@ public Table DefineTable(string moduleName, string name, T? initialValue, } var table = new Table(_store, initialValue, initial, maximum); - var ex = Define(moduleName, name, Interop.wasm_table_as_extern(table.Handle)); + var ex = Define(moduleName, name, Interop.wasm_table_as_extern(table.Handle.DangerousGetHandle())); if (ex != null) { @@ -637,6 +637,72 @@ public Table DefineTable(string moduleName, string name, T? initialValue, return table; } + /// + /// Defines a new host module. + /// + /// The module name of the module. + /// The name of the module. + /// The module to define in the host. + public void DefineModule(string moduleName, string name, Module module) + { + CheckDisposed(); + + if (moduleName is null) + { + throw new ArgumentNullException(nameof(moduleName)); + } + + if (name is null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (module is null) + { + throw new ArgumentNullException(nameof(module)); + } + + var ex = Define(moduleName, name, Interop.wasm_module_as_extern(module.Handle.DangerousGetHandle())); + + if (ex != null) + { + throw new WasmtimeException($"Failed to define module '{name}' in module '{moduleName}': {ex.Message}"); + } + } + + /// + /// Defines a new host instance. + /// + /// The module name of the instance. + /// The name of the instance. + /// The instance to define in the host. + public void DefineInstance(string moduleName, string name, Instance instance) + { + CheckDisposed(); + + if (moduleName is null) + { + throw new ArgumentNullException(nameof(moduleName)); + } + + if (name is null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (instance is null) + { + throw new ArgumentNullException(nameof(instance)); + } + + var ex = Define(moduleName, name, Interop.wasm_instance_as_extern(instance.Handle.DangerousGetHandle())); + + if (ex != null) + { + throw new WasmtimeException($"Failed to define instance '{name}' in module '{moduleName}': {ex.Message}"); + } + } + /// /// Instantiates a WebAssembly module. /// @@ -651,7 +717,21 @@ public Instance Instantiate(Module module) throw new ArgumentNullException(nameof(module)); } - return new Instance(_linker, module); + unsafe + { + var error = Interop.wasmtime_linker_instantiate(_linker, module.Handle, out var handle, out var trap); + + if (error != IntPtr.Zero) + { + throw WasmtimeException.FromOwnedError(error); + } + if (trap != IntPtr.Zero) + { + throw TrapException.FromOwnedTrap(trap); + } + + return new Instance(handle, module.Handle.DangerousGetHandle()); + } } /// @@ -696,7 +776,7 @@ private Function DefineFunction(string moduleName, string name, Delegate func, b } var function = new Function(_store, func, hasReturn); - var ex = Define(moduleName, name, Interop.wasm_func_as_extern(function.Handle)); + var ex = Define(moduleName, name, Interop.wasm_func_as_extern(function.Handle.DangerousGetHandle())); if (ex != null) { diff --git a/src/Imports/Import.cs b/src/Imports/Import.cs index 09cf354f..e7d11a81 100644 --- a/src/Imports/Import.cs +++ b/src/Imports/Import.cs @@ -15,10 +15,24 @@ internal Import(IntPtr importType) Handle = importType; var moduleName = Interop.wasm_importtype_module(Handle); - ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, (int)moduleName->size); + if (moduleName->size == UIntPtr.Zero) + { + ModuleName = String.Empty; + } + else + { + ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, (int)moduleName->size); + } var name = Interop.wasm_importtype_name(Handle); - Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size); + if (name is null || name->size == UIntPtr.Zero) + { + Name = String.Empty; + } + else + { + Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size); + } } } diff --git a/src/Imports/Imports.cs b/src/Imports/Imports.cs index bda7796e..070f439d 100644 --- a/src/Imports/Imports.cs +++ b/src/Imports/Imports.cs @@ -6,18 +6,17 @@ namespace Wasmtime.Imports /// /// Represents imported functions, globals, tables, and memories to a WebAssembly module. /// - public class Imports : IDisposable + public class Imports { - internal Imports(Module module) + internal Imports(Interop.wasm_importtype_vec_t imports) { - Interop.wasm_importtype_vec_t imports; - Interop.wasm_module_imports(module.Handle, out imports); - var all = new List((int)imports.size); var functions = new List(); var globals = new List(); var tables = new List(); var memories = new List(); + var instances = new List(); + var modules = new List(); for (int i = 0; i < (int)imports.size; ++i) { @@ -52,6 +51,18 @@ internal Imports(Module module) all.Add(memory); break; + case Interop.wasm_externkind_t.WASM_EXTERN_INSTANCE: + var instance = new InstanceImport(importType, externType); + instances.Add(instance); + all.Add(instance); + break; + + case Interop.wasm_externkind_t.WASM_EXTERN_MODULE: + var module = new ModuleImport(importType, externType); + modules.Add(module); + all.Add(module); + break; + default: throw new NotSupportedException("Unsupported import extern type."); } @@ -62,19 +73,11 @@ internal Imports(Module module) Globals = globals; Tables = tables; Memories = memories; + Instances = instances; + Modules = modules; All = all; } - /// - public unsafe void Dispose() - { - if (!(_imports.data is null)) - { - Interop.wasm_importtype_vec_delete(ref _imports); - _imports.data = null; - } - } - /// /// The imported functions required by a WebAssembly module. /// @@ -95,8 +98,16 @@ public unsafe void Dispose() /// public IReadOnlyList Memories { get; private set; } - internal IReadOnlyList All { get; private set; } + /// + /// The imported instances required by a WebAssembly module. + /// + public IReadOnlyList Instances { get; private set; } - private Interop.wasm_importtype_vec_t _imports; + /// + /// The imported modules required by a WebAssembly module. + /// + public IReadOnlyList Modules { get; private set; } + + internal IReadOnlyList All { get; private set; } } } diff --git a/src/Imports/InstanceImport.cs b/src/Imports/InstanceImport.cs new file mode 100644 index 00000000..a1c4ce2d --- /dev/null +++ b/src/Imports/InstanceImport.cs @@ -0,0 +1,35 @@ +using System; +using System.Diagnostics; + +namespace Wasmtime.Imports +{ + /// + /// Represents an instance imported to a WebAssembly module. + /// + public class InstanceImport : Import + { + internal InstanceImport(IntPtr importType, IntPtr externType) : base(importType) + { + Debug.Assert(Interop.wasm_externtype_kind(externType) == Interop.wasm_externkind_t.WASM_EXTERN_INSTANCE); + + var instanceType = Interop.wasm_externtype_as_instancetype_const(externType); + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_instancetype_exports(instanceType, out exports); + + try + { + Exports = new Exports.Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } + } + + /// + /// The exports of the instance. + /// + public Exports.Exports Exports { get; private set; } + } +} diff --git a/src/Imports/ModuleImport.cs b/src/Imports/ModuleImport.cs new file mode 100644 index 00000000..7afee677 --- /dev/null +++ b/src/Imports/ModuleImport.cs @@ -0,0 +1,52 @@ +using System; +using System.Diagnostics; + +namespace Wasmtime.Imports +{ + /// + /// Represents a module imported to a WebAssembly module. + /// + public class ModuleImport : Import + { + internal ModuleImport(IntPtr importType, IntPtr externType) : base(importType) + { + Debug.Assert(Interop.wasm_externtype_kind(externType) == Interop.wasm_externkind_t.WASM_EXTERN_MODULE); + + var moduleType = Interop.wasm_externtype_as_moduletype_const(externType); + + Interop.wasm_importtype_vec_t imports; + Interop.wasm_moduletype_imports(moduleType, out imports); + + try + { + Imports = new Imports(imports); + } + finally + { + Interop.wasm_importtype_vec_delete(ref imports); + } + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_moduletype_exports(moduleType, out exports); + + try + { + Exports = new Exports.Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } + } + + /// + /// The imports of the module. + /// + public Imports Imports { get; private set; } + + /// + /// The exports of the module. + /// + public Exports.Exports Exports { get; private set; } + } +} diff --git a/src/Instance.cs b/src/Instance.cs index 758e67b3..64e5b086 100644 --- a/src/Instance.cs +++ b/src/Instance.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using System.Dynamic; using Wasmtime.Externs; @@ -10,17 +9,37 @@ namespace Wasmtime /// /// Represents an instantiated WebAssembly module. /// - public class Instance : DynamicObject, IDisposable + public class Instance : DynamicObject, IDisposable, IImportable { /// - /// The WebAssembly module associated with the instantiation. + /// The exported functions of the instance. /// - public Module Module { get; private set; } + public IReadOnlyList Functions => _externs.Functions; /// - /// The external (instantiated) collection of functions, globals, tables, and memories. + /// The exported globals of the instance. /// - public Wasmtime.Externs.Externs Externs { get; private set; } + public IReadOnlyList Globals => _externs.Globals; + + /// + /// The exported tables of the instance. + /// + public IReadOnlyList Tables => _externs.Tables; + + /// + /// The exported memories of the instance. + /// + public IReadOnlyList Memories => _externs.Memories; + + /// + /// The exported instances of the instance. + /// + public IReadOnlyList Instances => _externs.Instances; + + /// + /// The exported modules of the instance. + /// + public IReadOnlyList Modules => _externs.Modules; /// public unsafe void Dispose() @@ -31,13 +50,22 @@ public unsafe void Dispose() Handle.SetHandleAsInvalid(); } - if (!(_externs.data is null)) + foreach (var instance in Instances) + { + instance.Dispose(); + } + + if (!(_externs is null)) { - Interop.wasm_extern_vec_delete(ref _externs); - _externs.data = null; + _externs.Dispose(); } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_instance_as_extern(Handle.DangerousGetHandle()); + } + /// public override bool TryGetMember(GetMemberBinder binder, out object? result) { @@ -74,41 +102,34 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object?[] args, return true; } - internal Instance(Interop.LinkerHandle linker, Module module) + internal Instance(Interop.InstanceHandle handle, IntPtr module) { - Module = module; - - unsafe - { - var error = Interop.wasmtime_linker_instantiate(linker, module.Handle, out var handle, out var trap); - Handle = handle; - - if (error != IntPtr.Zero) - { - throw WasmtimeException.FromOwnedError(error); - } - if (trap != IntPtr.Zero) - { - throw TrapException.FromOwnedTrap(trap); - } - } + Handle = handle; if (Handle.IsInvalid) { throw new WasmtimeException("Failed to create Wasmtime instance."); } - Interop.wasm_instance_exports(Handle, out _externs); + Interop.wasm_exporttype_vec_t exportsVec; + Interop.wasm_module_exports(module, out exportsVec); - Externs = new Wasmtime.Externs.Externs(Module.Exports, _externs); + try + { + var exports = new Wasmtime.Exports.Exports(exportsVec); + _externs = new Wasmtime.Externs.Externs(exports, Handle.DangerousGetHandle()); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exportsVec); + } - _functions = Externs.Functions.ToDictionary(f => f.Name); - _globals = Externs.Globals.ToDictionary(g => g.Name); + _functions = Functions.ToDictionary(f => f.Name); + _globals = Globals.ToDictionary(g => g.Name); } - internal Interop.InstanceHandle Handle { get; private set; } - private Interop.wasm_extern_vec_t _externs; + private Externs.Externs _externs; private Dictionary _functions; private Dictionary _globals; } diff --git a/src/Interop.cs b/src/Interop.cs index 67485dd7..42ff1cc8 100644 --- a/src/Interop.cs +++ b/src/Interop.cs @@ -268,21 +268,6 @@ protected override bool ReleaseHandle() } } - internal class WasiExportHandle : SafeHandle - { - public WasiExportHandle(IntPtr handle) : base(IntPtr.Zero, false /* not owned */) - { - SetHandle(handle); - } - - public override bool IsInvalid => handle == IntPtr.Zero; - - protected override bool ReleaseHandle() - { - return true; - } - } - internal class LinkerHandle : SafeHandle { public LinkerHandle() : base(IntPtr.Zero, true) @@ -313,21 +298,6 @@ protected override bool ReleaseHandle() } } - internal class ErrorHandle : SafeHandle - { - public ErrorHandle() : base(IntPtr.Zero, true) - { - } - - public override bool IsInvalid => handle == IntPtr.Zero; - - protected override bool ReleaseHandle() - { - wasmtime_error_delete(handle); - return true; - } - } - [StructLayout(LayoutKind.Sequential)] internal unsafe struct wasm_byte_vec_t { @@ -342,13 +312,6 @@ internal unsafe struct wasm_valtype_vec_t public IntPtr* data; } - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct wasm_export_vec_t - { - public UIntPtr size; - public IntPtr* data; - } - [StructLayout(LayoutKind.Sequential)] internal unsafe struct wasm_extern_vec_t { @@ -627,6 +590,8 @@ internal enum wasm_externkind_t : byte WASM_EXTERN_GLOBAL, WASM_EXTERN_TABLE, WASM_EXTERN_MEMORY, + WASM_EXTERN_MODULE, + WASM_EXTERN_INSTANCE, } internal enum wasm_mutability_t : byte @@ -647,25 +612,6 @@ internal static unsafe List ToValueKindList(wasm_valtype_vec_t* vec) return list; } - internal static wasm_valtype_vec_t ToValueTypeVec(IReadOnlyList collection) - { - wasm_valtype_vec_t vec; - wasm_valtype_vec_new_uninitialized(out vec, (UIntPtr)collection.Count); - - int i = 0; - foreach (var type in collection) - { - var valType = wasm_valtype_new((wasm_valkind_t)type); - unsafe - { - vec.data[i++] = valType.DangerousGetHandle(); - } - valType.SetHandleAsInvalid(); - } - - return vec; - } - internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList strings) { // Unfortunately .NET cannot currently marshal string[] as UTF-8 @@ -711,86 +657,29 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string // Byte vec imports - [DllImport(LibraryName)] - public static extern void wasm_byte_vec_new_empty(out wasm_byte_vec_t vec); - - [DllImport(LibraryName)] - public static extern void wasm_byte_vec_new_uninitialized(out wasm_byte_vec_t vec, UIntPtr length); - - [DllImport(LibraryName)] - public static unsafe extern void wasm_byte_vec_new(out wasm_byte_vec_t vec, UIntPtr length, byte* data); - - [DllImport(LibraryName)] - public static extern void wasm_byte_vec_copy(out wasm_byte_vec_t vec, ref wasm_byte_vec_t src); - [DllImport(LibraryName)] public static extern void wasm_byte_vec_delete(ref wasm_byte_vec_t vec); // Value type vec imports - [DllImport(LibraryName)] - public static extern void wasm_valtype_vec_new_empty(out wasm_valtype_vec_t vec); - [DllImport(LibraryName)] public static extern void wasm_valtype_vec_new_uninitialized(out wasm_valtype_vec_t vec, UIntPtr length); - [DllImport(LibraryName)] - public static unsafe extern void wasm_valtype_vec_new(out wasm_valtype_vec_t vec, UIntPtr length, IntPtr* data); - - [DllImport(LibraryName)] - public static extern void wasm_valtype_vec_copy(out wasm_valtype_vec_t vec, ref wasm_valtype_vec_t src); - - [DllImport(LibraryName)] - public static extern void wasm_valtype_vec_delete(ref wasm_valtype_vec_t vec); - // Extern vec imports - [DllImport(LibraryName)] - public static extern void wasm_extern_vec_new_empty(out wasm_extern_vec_t vec); - [DllImport(LibraryName)] public static extern void wasm_extern_vec_new_uninitialized(out wasm_extern_vec_t vec, UIntPtr length); - [DllImport(LibraryName)] - public static unsafe extern void wasm_extern_vec_new(out wasm_extern_vec_t vec, UIntPtr length, IntPtr* data); - - [DllImport(LibraryName)] - public static extern void wasm_extern_vec_copy(out wasm_extern_vec_t vec, ref wasm_extern_vec_t src); - [DllImport(LibraryName)] public static extern void wasm_extern_vec_delete(ref wasm_extern_vec_t vec); // Import type vec imports - [DllImport(LibraryName)] - public static extern void wasm_importtype_vec_new_empty(out wasm_importtype_vec_t vec); - - [DllImport(LibraryName)] - public static extern void wasm_importtype_vec_new_uninitialized(out wasm_importtype_vec_t vec, UIntPtr length); - - [DllImport(LibraryName)] - public static extern unsafe void wasm_importtype_vec_new(out wasm_importtype_vec_t vec, UIntPtr length, IntPtr* data); - - [DllImport(LibraryName)] - public static extern void wasm_importtype_vec_copy(out wasm_importtype_vec_t vec, ref wasm_importtype_vec_t src); - [DllImport(LibraryName)] public static extern void wasm_importtype_vec_delete(ref wasm_importtype_vec_t vec); // Export type vec imports - [DllImport(LibraryName)] - public static extern void wasm_exporttype_vec_new_empty(out wasm_exporttype_vec_t vec); - - [DllImport(LibraryName)] - public static extern void wasm_exporttype_vec_new_uninitialized(out wasm_exporttype_vec_t vec, UIntPtr length); - - [DllImport(LibraryName)] - public static unsafe extern void wasm_exporttype_vec_new(out wasm_exporttype_vec_t vec, UIntPtr length, IntPtr* data); - - [DllImport(LibraryName)] - public static extern void wasm_exporttype_vec_copy(out wasm_exporttype_vec_t vec, ref wasm_exporttype_vec_t src); - [DllImport(LibraryName)] public static extern void wasm_exporttype_vec_delete(ref wasm_exporttype_vec_t vec); @@ -819,10 +708,10 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string public static extern IntPtr wasmtime_module_new(EngineHandle engine, ref wasm_byte_vec_t bytes, out ModuleHandle module); [DllImport(LibraryName)] - public static extern void wasm_module_imports(ModuleHandle module, out wasm_importtype_vec_t imports); + public static extern void wasm_module_imports(IntPtr module, out wasm_importtype_vec_t imports); [DllImport(LibraryName)] - public static extern void wasm_module_exports(ModuleHandle module, out wasm_exporttype_vec_t exports); + public static extern void wasm_module_exports(IntPtr module, out wasm_exporttype_vec_t exports); [DllImport(LibraryName)] public static extern void wasm_module_delete(IntPtr module); @@ -843,9 +732,6 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public static extern wasm_externkind_t wasm_extern_kind(IntPtr ext); - [DllImport(LibraryName)] - public static extern IntPtr wasm_extern_type(IntPtr ext); - [DllImport(LibraryName)] public static extern IntPtr wasm_extern_as_func(IntPtr ext); @@ -858,7 +744,11 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public static extern IntPtr wasm_extern_as_memory(IntPtr ext); - // Externs + [DllImport(LibraryName)] + public static extern IntPtr wasm_extern_as_instance(IntPtr ext); + + [DllImport(LibraryName)] + public static extern IntPtr wasm_extern_as_module(IntPtr ext); [DllImport(LibraryName)] public static extern void wasm_extern_delete(IntPtr ext); @@ -880,6 +770,12 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public static extern IntPtr wasm_externtype_as_memorytype_const(IntPtr externType); + [DllImport(LibraryName)] + public static extern IntPtr wasm_externtype_as_instancetype_const(IntPtr externType); + + [DllImport(LibraryName)] + public static extern IntPtr wasm_externtype_as_moduletype_const(IntPtr externType); + // Function imports [DllImport(LibraryName)] @@ -895,16 +791,23 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string public static unsafe extern IntPtr wasm_func_call(IntPtr function, wasm_val_t* args, wasm_val_t* results); [DllImport(LibraryName)] - public static extern IntPtr wasm_func_as_extern(FunctionHandle function); + public static extern IntPtr wasm_func_as_extern(IntPtr function); + + [DllImport(LibraryName)] + public static extern IntPtr wasm_global_as_extern(IntPtr global); + + [DllImport(LibraryName)] + public static extern IntPtr wasm_memory_as_extern(IntPtr memory); [DllImport(LibraryName)] - public static extern IntPtr wasm_global_as_extern(GlobalHandle global); + public static extern IntPtr wasm_table_as_extern(IntPtr memory); [DllImport(LibraryName)] - public static extern IntPtr wasm_memory_as_extern(MemoryHandle memory); + public static extern IntPtr wasm_instance_as_extern(IntPtr instance); [DllImport(LibraryName)] - public static extern IntPtr wasm_table_as_extern(TableHandle memory); + public static extern IntPtr wasm_module_as_extern(IntPtr module); + // Function type imports @@ -916,14 +819,11 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string // Instance imports - [DllImport(LibraryName)] - public static extern unsafe InstanceHandle wasm_instance_new(StoreHandle store, ModuleHandle module, IntPtr* imports, out IntPtr trap); - [DllImport(LibraryName)] public static extern void wasm_instance_delete(IntPtr ext); [DllImport(LibraryName)] - public static extern void wasm_instance_exports(InstanceHandle instance, out wasm_extern_vec_t exports); + public static extern void wasm_instance_exports(IntPtr instance, out wasm_extern_vec_t exports); // Function type imports @@ -1017,15 +917,28 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public static extern void wasm_global_delete(IntPtr global); - [DllImport(LibraryName)] - public static extern IntPtr wasm_global_type(IntPtr global); - [DllImport(LibraryName)] public static unsafe extern void wasm_global_get(IntPtr global, wasm_val_t* value); [DllImport(LibraryName)] public static unsafe extern void wasm_global_set(IntPtr global, wasm_val_t* value); + // Instance type imports + + [DllImport(LibraryName)] + public static extern void wasm_instancetype_delete(IntPtr instanceType); + + [DllImport(LibraryName)] + public static extern void wasm_instancetype_exports(IntPtr instanceType, out wasm_exporttype_vec_t exports); + + // Module type imports + + [DllImport(LibraryName)] + public static extern void wasm_moduletype_imports(IntPtr moduleType, out wasm_importtype_vec_t imports); + + [DllImport(LibraryName)] + public static extern void wasm_moduletype_exports(IntPtr moduleType, out wasm_exporttype_vec_t exports); + // Memory imports [DllImport(LibraryName)] @@ -1034,9 +947,6 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public static extern void wasm_memory_delete(IntPtr memory); - [DllImport(LibraryName)] - public static extern IntPtr wasm_memory_type(MemoryHandle memory); - [DllImport(LibraryName)] public static unsafe extern byte* wasm_memory_data(IntPtr memory); @@ -1044,11 +954,11 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string public static extern UIntPtr wasm_memory_data_size(IntPtr memory); [DllImport(LibraryName)] - public static extern uint wasm_memory_size(MemoryHandle memory); + public static extern uint wasm_memory_size(IntPtr memory); [DllImport(LibraryName)] [return: MarshalAs(UnmanagedType.I1)] - public static extern bool wasm_memory_grow(MemoryHandle memory, uint delta); + public static extern bool wasm_memory_grow(IntPtr memory, uint delta); // Table imports @@ -1096,9 +1006,6 @@ internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList string [DllImport(LibraryName)] public unsafe static extern void wasi_config_set_argv(WasiConfigHandle config, int argc, byte** argv); - [DllImport(LibraryName)] - public static extern void wasi_config_inherit_argv(WasiConfigHandle config); - [DllImport(LibraryName)] public static extern unsafe void wasi_config_set_env( WasiConfigHandle config, @@ -1149,6 +1056,7 @@ public static extern bool wasi_config_preopen_dir( ); // WASI instance + [DllImport(LibraryName)] public static extern WasiInstanceHandle wasi_instance_new( StoreHandle store, @@ -1183,6 +1091,9 @@ out IntPtr trap [DllImport(LibraryName)] public static extern void wasmtime_config_wasm_multi_value_set(WasmConfigHandle config, [MarshalAs(UnmanagedType.I1)] bool enable); + [DllImport(LibraryName)] + public static extern void wasmtime_config_wasm_module_linking_set(WasmConfigHandle config, [MarshalAs(UnmanagedType.I1)] bool enable); + [DllImport(LibraryName)] public static extern IntPtr wasmtime_config_strategy_set(WasmConfigHandle config, wasmtime_strategy_t strategy); @@ -1215,10 +1126,12 @@ out IntPtr trap public static extern IntPtr wasmtime_linker_define_wasi(LinkerHandle linker, WasiInstanceHandle wasi); [DllImport(LibraryName)] - public static extern IntPtr wasmtime_linker_define_instance(LinkerHandle linker, ref wasm_byte_vec_t name, InstanceHandle instance); + public static extern IntPtr wasmtime_linker_instantiate(LinkerHandle linker, ModuleHandle module, out InstanceHandle instance, out IntPtr trap); + + // Wasmtime instance functions [DllImport(LibraryName)] - public static extern IntPtr wasmtime_linker_instantiate(LinkerHandle linker, ModuleHandle module, out InstanceHandle instance, out IntPtr trap); + public static unsafe extern IntPtr wasmtime_instance_new(StoreHandle linker, IntPtr module, IntPtr* imports, UIntPtr numImports, out InstanceHandle instance, out IntPtr trap); // Caller functions diff --git a/src/Memory.cs b/src/Memory.cs index 27078e2c..9a8a2337 100644 --- a/src/Memory.cs +++ b/src/Memory.cs @@ -5,7 +5,7 @@ namespace Wasmtime /// /// Represents a WebAssembly memory. /// - public class Memory : MemoryBase, IDisposable + public class Memory : MemoryBase, IDisposable, IImportable { /// /// The size, in bytes, of a WebAssembly memory page. @@ -32,6 +32,11 @@ public void Dispose() } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_memory_as_extern(Handle.DangerousGetHandle()); + } + internal Memory(Interop.StoreHandle store, uint minimum = 1, uint maximum = uint.MaxValue) { if (minimum == 0) diff --git a/src/MemoryBase.cs b/src/MemoryBase.cs index 78754ff0..04b6e27a 100644 --- a/src/MemoryBase.cs +++ b/src/MemoryBase.cs @@ -6,6 +6,11 @@ namespace Wasmtime { public abstract class MemoryBase { + /// + /// The current size, in WebAssembly page units, of the memory. + /// + public uint Size => Interop.wasm_memory_size(MemoryHandle); + /// /// The span of the memory. /// @@ -231,6 +236,16 @@ public void WriteDouble(int address, double value) } } + /// + /// Grows the memory by the specified number of pages. + /// + /// The number of WebAssembly pages to grow the memory by. + /// Returns true if the memory grew or false if it would exceed the maximum size. + public bool Grow(uint delta) + { + return Interop.wasm_memory_grow(MemoryHandle, delta); + } + protected abstract IntPtr MemoryHandle { get; } } } diff --git a/src/Module.cs b/src/Module.cs index cd67cab5..8d83714e 100644 --- a/src/Module.cs +++ b/src/Module.cs @@ -5,10 +5,25 @@ namespace Wasmtime { + /// + /// Implemented by types that can be imported by WebAssembly modules. + /// + public interface IImportable + { + /// + /// Gets the extern handle for the importable. + /// + /// + /// This interface is internal to Wasmtime and not intended to be implemented by users. + /// + /// Returns the extern handle for the importable. + IntPtr GetHandle(); + } + /// /// Represents a WebAssembly module. /// - public class Module : IDisposable + public class Module : IDisposable, IImportable { /// /// The name of the module. @@ -168,6 +183,51 @@ public static Module FromTextStream(Engine engine, string name, Stream stream) return FromText(engine, name, reader.ReadToEnd()); } + /// + /// Instantiates a given a set of imports. + /// + /// The store to associate with the instance. + /// The imports to use for the instantiations. + /// Returns a new . + public Instance Instantiate(Store store, params IImportable[] imports) + { + if (store is null) + { + throw new ArgumentNullException(nameof(store)); + } + + if (imports is null) + { + throw new ArgumentNullException(nameof(imports)); + } + + unsafe + { + IntPtr* handles = stackalloc IntPtr[imports.Length]; + + for (int i = 0; i < imports.Length; ++i) + { + unsafe + { + handles[i] = imports[i].GetHandle(); + } + } + + var error = Interop.wasmtime_instance_new(store.Handle, Handle.DangerousGetHandle(), handles, (UIntPtr)imports.Length, out var instance, out var trap); + + if (error != IntPtr.Zero) + { + throw WasmtimeException.FromOwnedError(error); + } + if (trap != IntPtr.Zero) + { + throw TrapException.FromOwnedTrap(trap); + } + + return new Instance(instance, Handle.DangerousGetHandle()); + } + } + /// public void Dispose() { @@ -176,15 +236,11 @@ public void Dispose() Handle.Dispose(); Handle.SetHandleAsInvalid(); } + } - if (!(Imports is null)) - { - Imports.Dispose(); - - // once Module is disposed, nothing in Module should be used anyways. - // keeping `Imports` to appear as a non-nullable makes things simpler for developers. - Imports = null!; - } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_module_as_extern(Handle.DangerousGetHandle()); } internal Module(Interop.EngineHandle engine, string name, ReadOnlySpan bytes) @@ -208,8 +264,30 @@ internal Module(Interop.EngineHandle engine, string name, ReadOnlySpan byt } Name = name; - Imports = new Wasmtime.Imports.Imports(this); - Exports = new Wasmtime.Exports.Exports(this); + + Interop.wasm_importtype_vec_t imports; + Interop.wasm_module_imports(Handle.DangerousGetHandle(), out imports); + + try + { + Imports = new Wasmtime.Imports.Imports(imports); + } + finally + { + Interop.wasm_importtype_vec_delete(ref imports); + } + + Interop.wasm_exporttype_vec_t exports; + Interop.wasm_module_exports(Handle.DangerousGetHandle(), out exports); + + try + { + Exports = new Wasmtime.Exports.Exports(exports); + } + finally + { + Interop.wasm_exporttype_vec_delete(ref exports); + } } internal Interop.ModuleHandle Handle { get; private set; } diff --git a/src/MutableGlobal.cs b/src/MutableGlobal.cs index 9c8bbbc6..bcc5728b 100644 --- a/src/MutableGlobal.cs +++ b/src/MutableGlobal.cs @@ -6,7 +6,7 @@ namespace Wasmtime /// /// Represents a mutable WebAssembly global value. /// - public class MutableGlobal : IDisposable + public class MutableGlobal : IDisposable, IImportable { /// /// The value of the global. @@ -54,6 +54,11 @@ public void Dispose() } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_global_as_extern(Handle.DangerousGetHandle()); + } + internal MutableGlobal(Interop.StoreHandle store, T initialValue) { if (!Interop.TryGetValueKind(typeof(T), out var kind)) diff --git a/src/Table.cs b/src/Table.cs index bc47a9a5..a76ca3f8 100644 --- a/src/Table.cs +++ b/src/Table.cs @@ -6,7 +6,7 @@ namespace Wasmtime /// /// Represents a WebAssembly table. /// - public class Table : IDisposable where T : class + public class Table : IDisposable, IImportable where T : class { /// /// Gets the value kind of the table. @@ -102,6 +102,11 @@ public void Dispose() } } + IntPtr IImportable.GetHandle() + { + return Interop.wasm_table_as_extern(Handle.DangerousGetHandle()); + } + internal Table(Interop.StoreHandle store, T? initialValue, uint initial, uint maximum) { if (!Interop.TryGetValueKind(typeof(T), out var kind)) diff --git a/src/Wasmtime.csproj b/src/Wasmtime.csproj index e90ba7d4..3193fc16 100644 --- a/src/Wasmtime.csproj +++ b/src/Wasmtime.csproj @@ -20,7 +20,7 @@ true snupkg https://github.com/bytecodealliance/wasmtime-dotnet - Update Wasmtime to 0.21.0. + Update Wasmtime to 0.22.0. A .NET API for Wasmtime, a standalone WebAssembly runtime webassembly, .net, wasm, wasmtime Wasmtime diff --git a/tests/GlobalExportsTests.cs b/tests/GlobalExportsTests.cs index 6c4f5397..0fd0b23b 100644 --- a/tests/GlobalExportsTests.cs +++ b/tests/GlobalExportsTests.cs @@ -46,7 +46,7 @@ public void ItCreatesExternsForTheGlobals() using var instance = Host.Instantiate(Fixture.Module); dynamic dyn = instance; - var globals = instance.Externs.Globals; + var globals = instance.Globals; globals.Count.Should().Be(8); var i32 = globals[0]; diff --git a/tests/MemoryExportsTests.cs b/tests/MemoryExportsTests.cs index 0cf7a93b..6d58e867 100644 --- a/tests/MemoryExportsTests.cs +++ b/tests/MemoryExportsTests.cs @@ -44,9 +44,9 @@ public void ItCreatesExternsForTheMemories() { using var instance = Host.Instantiate(Fixture.Module); - instance.Externs.Memories.Count.Should().Be(1); + instance.Memories.Count.Should().Be(1); - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; memory.ReadString(0, 11).Should().Be("Hello World"); int written = memory.WriteString(0, "WebAssembly Rocks!"); memory.ReadString(0, written).Should().Be("WebAssembly Rocks!"); diff --git a/tests/ModuleLinkingTests.cs b/tests/ModuleLinkingTests.cs new file mode 100644 index 00000000..3f3216e8 --- /dev/null +++ b/tests/ModuleLinkingTests.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using Xunit; +using Wasmtime; + +namespace Wasmtime.Tests +{ + public class ModuleLinkingTests : IDisposable + { + public ModuleLinkingTests() + { + Engine = new EngineBuilder() + .WithModuleLinking(true) + .Build(); + Store = new Store(Engine); + Host = new Host(Store); + } + + private Engine Engine { get; set; } + + private Store Store { get; set; } + + private Host Host { get; set; } + + [Fact] + public void ItExposesModuleImports() + { + using var module = Module.FromText(Engine, "test", @"(module (import ""a"" ""b"" (module)))"); + + module.Imports.Modules.Count.Should().Be(1); + module.Imports.Modules[0].ModuleName.Should().Be("a"); + module.Imports.Modules[0].Name.Should().Be("b"); + } + + [Fact] + public void ItExposesModuleExports() + { + using var module = Module.FromText(Engine, "test", @"(module (module (export ""a"")))"); + + module.Exports.Modules.Count.Should().Be(1); + module.Exports.Modules[0].Name.Should().Be("a"); + } + + [Fact] + public void ItExposesInstanceImports() + { + using var module = Module.FromText(Engine, "test", @"(module (import ""a"" ""b"" (instance (export ""c"" (memory 1)))))"); + + module.Imports.Instances.Count.Should().Be(1); + module.Imports.Instances[0].ModuleName.Should().Be("a"); + module.Imports.Instances[0].Name.Should().Be("b"); + module.Imports.Instances[0].Exports.Memories.Count.Should().Be(1); + module.Imports.Instances[0].Exports.Memories[0].Name.Should().Be("c"); + } + + [Fact] + public void ItExposesInstanceExports() + { + using var module = Module.FromText(Engine, "test", @"(module (module (table (export ""b"") 1 10 funcref)) (instance (export ""a"") (instantiate 0)))"); + + module.Exports.Instances.Count.Should().Be(1); + module.Exports.Instances[0].Name.Should().Be("a"); + module.Exports.Instances[0].Exports.Tables.Count.Should().Be(1); + module.Exports.Instances[0].Exports.Tables[0].Name.Should().Be("b"); + } + + [Fact] + public void ItInstantiatesAModule() + { + using var importModule = Module.FromText(Engine, "other", @"(module (import ""a"" (func)) (export ""b"" (func 0)) (memory 1))"); + using var module = Module.FromText(Engine, "test", @"(module (import ""a"" (module (import ""b"" (func)))) (export ""c"" (module 0)))"); + + var called = false; + using var instance = module.Instantiate(Store, importModule); + instance.Modules.Count.Should().Be(1); + using var other = instance.Modules[0].Instantiate(Store, Function.FromCallback(Store, () => { called = true; })); + other.Functions.Count.Should().Be(1); + other.Functions[0].Invoke(); + called.Should().BeTrue(); + } + + public void Dispose() + { + Engine.Dispose(); + Store.Dispose(); + Host.Dispose(); + } + } +} diff --git a/tests/TableExportsTests.cs b/tests/TableExportsTests.cs index d87660a2..a29e6591 100644 --- a/tests/TableExportsTests.cs +++ b/tests/TableExportsTests.cs @@ -45,7 +45,7 @@ public void ItCreatesExternsForTheTables() { using var instance = Host.Instantiate(Fixture.Module); - var tables = instance.Externs.Tables; + var tables = instance.Tables; tables.Count.Should().Be(3); var table1 = tables[0]; diff --git a/tests/WasiSnapshot0Tests.cs b/tests/WasiSnapshot0Tests.cs index a15b06f0..7622986d 100644 --- a/tests/WasiSnapshot0Tests.cs +++ b/tests/WasiSnapshot0Tests.cs @@ -31,7 +31,7 @@ public void ItHasNoEnvironmentByDefault() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(0, memory.ReadInt32(0)); @@ -55,7 +55,7 @@ public void ItHasSpecifiedEnvironment() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(env.Count, memory.ReadInt32(0)); @@ -80,7 +80,7 @@ public void ItInheritsEnvironment() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(Environment.GetEnvironmentVariables().Keys.Count, memory.ReadInt32(0)); @@ -94,7 +94,7 @@ public void ItHasNoArgumentsByDefault() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(0, memory.ReadInt32(0)); @@ -119,7 +119,7 @@ public void ItHasSpecifiedArguments() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(args.Count, memory.ReadInt32(0)); @@ -144,7 +144,7 @@ public void ItInheritsArguments() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(Environment.GetCommandLineArgs().Length, memory.ReadInt32(0)); @@ -166,7 +166,7 @@ public void ItSetsStdIn() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; memory.WriteInt32(0, 8); memory.WriteInt32(4, MESSAGE.Length); @@ -199,7 +199,7 @@ public void ItSetsStdOutAndStdErr(int fd) using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; memory.WriteInt32(0, 8); memory.WriteInt32(4, MESSAGE.Length); memory.WriteString(8, MESSAGE); @@ -225,7 +225,7 @@ public void ItSetsPreopenDirectories() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; var fileName = Path.GetFileName(file.Path); memory.WriteString(0, fileName); diff --git a/tests/WasiTests.cs b/tests/WasiTests.cs index ded89045..5e9f1a44 100644 --- a/tests/WasiTests.cs +++ b/tests/WasiTests.cs @@ -32,7 +32,7 @@ public void ItHasNoEnvironmentByDefault() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(0, memory.ReadInt32(0)); @@ -56,7 +56,7 @@ public void ItHasSpecifiedEnvironment() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(env.Count, memory.ReadInt32(0)); @@ -81,7 +81,7 @@ public void ItInheritsEnvironment() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_environ_sizes_get(0, 4)); Assert.Equal(Environment.GetEnvironmentVariables().Keys.Count, memory.ReadInt32(0)); @@ -95,7 +95,7 @@ public void ItHasNoArgumentsByDefault() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(0, memory.ReadInt32(0)); @@ -120,7 +120,7 @@ public void ItHasSpecifiedArguments() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(args.Count, memory.ReadInt32(0)); @@ -145,7 +145,7 @@ public void ItInheritsArguments() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; Assert.Equal(0, inst.call_args_sizes_get(0, 4)); Assert.Equal(Environment.GetCommandLineArgs().Length, memory.ReadInt32(0)); @@ -167,7 +167,7 @@ public void ItSetsStdIn() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; memory.WriteInt32(0, 8); memory.WriteInt32(4, MESSAGE.Length); @@ -200,7 +200,7 @@ public void ItSetsStdOutAndStdErr(int fd) using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; memory.WriteInt32(0, 8); memory.WriteInt32(4, MESSAGE.Length); memory.WriteString(8, MESSAGE); @@ -226,7 +226,7 @@ public void ItSetsPreopenDirectories() using var instance = Host.Instantiate(Fixture.Module); dynamic inst = instance; - var memory = instance.Externs.Memories[0]; + var memory = instance.Memories[0]; var fileName = Path.GetFileName(file.Path); memory.WriteString(0, fileName); diff --git a/tests/Wasmtime.Tests.csproj b/tests/Wasmtime.Tests.csproj index 03a1fd81..8decfbd0 100644 --- a/tests/Wasmtime.Tests.csproj +++ b/tests/Wasmtime.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 false