Hi, I'm trying to follow the instructions here: https://github.com/bytecodealliance/componentize-dotnet
My understanding is that I need a Windows machine, but not sure what other pre-reqs need to be on that machine for it to work. I've followed the instructions on the page, with only dotnet installed, but am getting build errors:
EXEC : error : Unable to load DLL 'libLLVM' or one of its dependencies: The specified module could not be found. [C:\Us
ers\mikkelhegn\dotnetstring\dotnetstring.csproj]
I've tried adding: runtime.win-x64.Microsoft.DotNet.ILCompiler - based on a hint in this issue: https://github.com/bytecodealliance/componentize-dotnet/issues/13, but also without success.
Next up installing Visual Studio with WebAssembly build tools. Am I on the right path?
:-)
Now I'm at Python was not found - I'll think I may need to try and build the SDK myself.
Oh - there is one in the latest release run: https://github.com/bytecodealliance/componentize-dotnet/actions/runs/9409845824
Build locally from main solved this.
We just got the code moved over and updated, so we don't have a release yet. Using the pacakges from the latest build should work on Windows. If it doesn't feel free to open an issue or let me know here
In trying to build this, I'm having a hard time figuring out what the C# namespace, interface, etc, ends up being called based on a WIT looking like this:
package wasmio:samples;
world plugin {
export transform: func(input: string) -> string;
}
Can I find the bindings being generated somewhere to help me?
they should be in the obj\Debug\net8.0\wasi-wasm\wit_bindgen folder or something similiar
The namespace in that should start with PluginWorld
Is it true that functions directly in worlds is not supported by the bindings generator? I seem to not get bindings I can use with that. (Or there is some C# stuff I don't know about :-)).
That should work I believe, there would be an interface that needs to implemented.
Put this in and get the following:
namespace PluginWorld {
public interface IPluginWorld {
static abstract string Transform(string input);
}
....
an implementation would be like:
namespace PluginWorld
{
public class PluginWorldImpl : IPluginWorld
{
public static string Transform(string input)
{
return input.ToUpperInvariant();
}
}
}
I'll give that a try
got a release out https://github.com/bytecodealliance/componentize-dotnet/releases
also built a sample app using that wit file: https://github.com/jsturtevant/PluginApp
Awesome! just followed the Readme.md to create a console app on a Windows x64 machine. Had two build warning, but the .wasm file runs on my MacOS aarch64
If you create an issue on the repo with the log warnings, can trake them for fixes if appropriate. I know I get warnings about switching from wasm-tools to wac which is tracked already
Created an issue here: https://github.com/bytecodealliance/componentize-dotnet/issues/23
I'm still struggling with building a library exporting a function - a component. This repo builds and produces a working component. However, how did I get around not providing the wit namespace in the implementation? And what should it be? It seems the binding generators are not happy with whatever way I'm trying to do it, with a namespace.
https://github.com/mikkelhegn/dotnet-component
are you getting a specific error?
I just realized you pushed the exact same code to a repo above - sorry for not seeing that. My code works (as it's the same as yours).
The confusion on my end was that the implementation in https://github.com/jsturtevant/PluginApp/blob/main/plugin.cs did not use the wit exports in the namespace (e.g., namespace PluginWorld.wit.exports.wasmio.samples;). I assume this is because the wit file does not define an interface, but an inlined export. I'm not sure how intuitive that is, but it got me confused.
ah ok, Yes I guess that is a bit strange. We might event run into an issue where you have two plugin worlds in different wit name spaces and so we could have a conflict in the .net code?
I haven't spent much time with other generators, how is this handled in go or rust?
Maybe @Alex Crichton or @Mossaka (Joe) can help comment on that?
James Sturtevant said:
I haven't spent much time with other generators, how is this handled in go or rust?
I don't know about Go, but in Rust, the module(s) generated by wit-bindgen can easily be nested in other modules by the application programmer to avoid any possible name collisions, so it's not a problem in practice.
One thing missing in componentize-dotnet is to be able to generate the bindings without building the component. That way the tooling can help guide you. I actually con't know if that's possible today?
You can do it pretty easily using the wit-bindgen CLI directly, but I agree that it would be nice if componentize-dotnet exposed that somehow too. Not sure what the IDE-friendly, non-CLI way to do that might be, though.
The bindings are generated into a intermediate folder, Would it help to have it in the project its self so you can find them?
would you want to check those in?
@Mikkel Mørk Hegnhøj This is mostly about discoverbility? the files should be generated when a file is touched in an idea (using incremental builds). Right now they are hidden, which I found odd as well. I think I generally like to have generated code checked into source so can see and review the changes, Maybe we can put them in a folder in the source directory that gets checked in. Thoguhts?
Yes, I think that makes a lot of sense. That workflow matches what's happening in both Rust, and to some degree what you can do with componentize-py as well.
https://github.com/bytecodealliance/componentize-dotnet/issues/29
Reviving as I got back to this exercise today. In the new release (0.2.0.preview0004) the namespace seems to have simplified in my interface implementation.
My implementation used to be:
namespace PluginWorld.wit.exports.wasmio.samples;
public class PluginWorldImpl : IPluginWorld
{
public static string Transform(string input)
{
return input.ToUpperInvariant();
}
}
Causing this error:
C:\Users\mikkelhegn\dotnet-component\obj\Debug\net8.0\wasi-wasm\wit_bindgen\Plugin.cs(111,23): error CS0103: The name 'PluginWorldImpl' does not exist in
the current context [C:\Users\mikkelhegn\dotnet-component\dotnet-component.csproj]
Changing to this resolved it:
namespace PluginWorld;
public class PluginWorldImpl : IPluginWorld
{
public static string Transform(string input)
{
return input.ToUpperInvariant();
}
}
For reference the WIT:
package wasmio:samples;
world plugin {
export transform: func(input: string) -> string;
}
If I'm not doing anything "wrong", the README needs an update, but wanted to check here first. @James Sturtevant
yes, wit-bindgen has had a few changes over the last few months to the generated code. Its likely just a readme update, which I thoough I had covered in https://github.com/bytecodealliance/componentize-dotnet/pull/37/files but maybe got them wrong (I copied the examples out of our samples)
but your example is working now?
Hi James, yes it is, however only builds on net8.0 on Windows. Neither net9 or macOS (8 or 9) are working, but I think that's known.
I created a small update to the readme as I went through it: https://github.com/bytecodealliance/componentize-dotnet/pull/39
Yes only Windows works, we have some work in progress to support Linux. .net 9 with llvm compilier should work on Windows (CI passes) but .net 9's regular suppport has some challenges https://github.com/bytecodealliance/componentize-dotnet/pull/38 and along with a few missing configuration setting.
Do you think adding a table of what is/isn't supported would help?
Last updated: Dec 06 2025 at 06:05 UTC