WitBindgen.Runtime
0.1.3
dotnet add package WitBindgen.Runtime --version 0.1.3
NuGet\Install-Package WitBindgen.Runtime -Version 0.1.3
<PackageReference Include="WitBindgen.Runtime" Version="0.1.3" />
<PackageVersion Include="WitBindgen.Runtime" Version="0.1.3" />
<PackageReference Include="WitBindgen.Runtime" />
paket add WitBindgen.Runtime --version 0.1.3
#r "nuget: WitBindgen.Runtime, 0.1.3"
#:package WitBindgen.Runtime@0.1.3
#addin nuget:?package=WitBindgen.Runtime&version=0.1.3
#tool nuget:?package=WitBindgen.Runtime&version=0.1.3
wit-bindgen-dotnet
C# source generator that produces bindings from WIT (WebAssembly Interface Types) definitions, enabling .NET WebAssembly components using the Component Model.
What it does
wit-bindgen-dotnet reads .wit files at compile time and generates C# code for both sides of the component boundary:
- Guest side (
WitBindgen.SourceGenerator) — generatesDllImportstubs for imports andUnmanagedCallersOnlyexports, so your .NET code can be compiled to a WASM component via NativeAOT-LLVM. - Host side (
Wasmtime.SourceGeneratorfrom wasmtime-dotnet) — generates an abstract*Importsclass you implement to provide host functions, and a typed*Exportswrapper to call into the guest.
Supported WIT types
| WIT type | C# mapping |
|---|---|
Primitives (u8..u64, s8..s64, f32, f64, bool, char, string) |
Native C# types |
list<T> |
ReadOnlySpan<T> (imports), arrays (exports) |
option<T> |
T? |
result<T, E> |
Generated result types |
record |
struct with fields |
enum |
C# enum |
flags |
C# [Flags] enum |
variant |
struct with discriminant + payload |
resource |
Abstract class with handle table (host), DllImport stubs (guest) |
tuple<...> |
C# tuples |
borrow<T> |
Handle parameter |
Project structure
wit-bindgen-dotnet/
src/
WitBindgen.SourceGenerator/ # Guest-side Roslyn source generator
WitBindgen.Runtime/ # Runtime helpers for guest components
examples/
HelloWorld/ # Minimal guest example
Calculator/ # Guest WASM component (NativeAOT-LLVM)
CalculatorHost/ # Host that loads and runs the calculator
tests/
WitBindgen.Tests/ # Parser and code generation tests
external/
wasmtime-dotnet/ # Submodule: Wasmtime .NET bindings + host source generator
Prerequisites
- .NET 10 SDK
- NativeAOT-LLVM workload (for publishing guest components to WASM)
Building
Clone with submodules:
git clone --recurse-submodules https://github.com/andreakarasho/wit-bindgen-dotnet.git
cd wit-bindgen-dotnet
Build everything:
dotnet build WitBindgen.slnx
Run tests:
dotnet test WitBindgen.slnx
Usage
Writing a guest component
1. Define your WIT world:
// wit/hello.wit
package example:hello@1.0.0;
interface console {
log: func(message: string);
}
world hello-world {
import console;
import get-name: func() -> string;
export run: func() -> string;
}
2. Create the project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="10.0.0-*" />
<PackageReference Include="runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM" Version="10.0.0-*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="WitBindgen.SourceGenerator" Version="0.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="WitBindgen.Runtime" Version="0.1.0" />
</ItemGroup>
<ItemGroup>
<WasmComponentTypeWit Include="wit\hello.wit" />
</ItemGroup>
</Project>
The NuGet package sets WASI-WASM defaults (AllowUnsafeBlocks, SelfContained, etc.) automatically. You also need to add the NativeAOT-LLVM compiler packages so the project compiles to .wasm:
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="10.0.0-*" />
<PackageReference Include="runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM" Version="10.0.0-*" />
</ItemGroup>
3. Implement the exports:
The source generator creates partial classes in the Wit.<Namespace>.<Package> namespace. You implement the exported functions as partial methods:
namespace Wit.Example.Hello;
public static partial class HelloWorld
{
public static partial string Run()
{
// Call imported functions
var name = Imports.GetName();
Console.Log($"Hello, {name}!");
return $"Hello, {name}!";
}
}
4. Publish to WASM:
dotnet publish -c Release
Writing a host application
1. Create the project referencing Wasmtime and its source generator, with the same WIT file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="path/to/Wasmtime.csproj" />
<ProjectReference Include="path/to/Wasmtime.SourceGenerator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="path/to/hello.wit" />
</ItemGroup>
</Project>
2. Implement the imports by subclassing the generated abstract *Imports class:
class HelloImportsImpl : Wit.Example.Hello.HelloWorldImports
{
public override void Log(string message)
{
Console.WriteLine($"[guest] {message}");
}
public override string GetName()
{
return "World";
}
}
3. Load and run the component:
using Wasmtime;
using var engine = new Engine();
using var linker = new Linker(engine);
linker.AddWasiP2();
var imports = new HelloImportsImpl();
linker.Define(imports);
var bytes = File.ReadAllBytes("hello.wasm");
using var component = Component.Compile(engine, bytes);
using var store = new Store(engine);
store.AddWasiP2();
var instance = store.GetComponentInstance(component, linker);
var exports = new Wit.Example.Hello.HelloWorldExports(instance, store);
var result = exports.Run();
Console.WriteLine(result); // "Hello, World!"
How it works
┌──────────────┐
│ .wit file │
└──────┬───────┘
│
┌────────────┴────────────┐
│ │
┌──────────▼──────────┐ ┌──────────▼──────────┐
│ WitBindgen.Source │ │ Wasmtime.Source │
│ Generator (guest) │ │ Generator (host) │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
┌──────────▼──────────┐ ┌──────────▼──────────┐
│ DllImport stubs │ │ Abstract *Imports │
│ + export wrappers │ │ + typed *Exports │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
┌──────────▼──────────┐ ┌──────────▼──────────┐
│ NativeAOT-LLVM │ │ Wasmtime runtime │
│ → .wasm component │ │ → loads .wasm │
└─────────────────────┘ └─────────────────────┘
Both generators read the same .wit file and produce complementary code. The guest compiles to a .wasm component that the host loads and runs via Wasmtime.
License
Apache-2.0 WITH LLVM-exception
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.3 | 38 | 2/17/2026 |
| 0.1.2 | 42 | 2/17/2026 |
| 0.1.1 | 40 | 2/16/2026 |
| 0.1.0 | 46 | 2/16/2026 |
| 0.0.0-alpha.0.9 | 42 | 2/16/2026 |
| 0.0.0-alpha.0.7 | 37 | 2/16/2026 |