Hey folks, initially I built a platform in Rust (honestly I'm an F# developer, I don't know why I chose Rust, i should have just gone the .NET route), and I have not been having a good time. Insane compile times, constantly running out of disk space, etc etc.
I saw way back like ~1 year ago, there was documentation in alpha 4 for .net platforms.
Before I start a whole rewrite, is .NET intended to be a strong platform target going forward? Are there any feature gaps / issues I should be aware of relative to Rust?
I'd love to help make that happen! :smiley:
I know C# has a struct keyword and that there's an API for loading dynamic libraries, so I'd probably start there in terms of glue - just making a glue spec to generate .net bindings to Roc records consisting only of types with no heap allocations (e.g. bools, numbers, nested records)
things would get more interesting when you start wanting to convert .net types into Roc structures
Examples:
https://github.com/roc-lang/roc/blob/main/src/glue/src/CGlue.roc
https://github.com/roc-lang/roc/blob/main/src/glue/src/RustGlue.roc
https://github.com/roc-lang/roc/blob/main/src/glue/src/ZigGlue.roc
https://github.com/roc-lang/roc/blob/main/src/glue/src/DebugGlue.roc
Run the dotnet glue (after porting):
roc glue glue/DotNetGlue.roc host/ platform/main.roc
dotnet build host/myproject.sln
roc build app/main.roc
arg 1) path to glue generator
(fork one of the above as a template, or give file to LLM & command it to port to dotnet)
arg 2) destination for generated .net glue
arg 3) the platform that is being used as inputs for the glue
This is super helpful!! Thank you!
Chander Ramesh has marked this topic as resolved.
And as for a dotnet platform itself, luke has made some roc-platform-template-{lang} templates that you can reference, with some basic-cli-like effects; stdout etc.
https://github.com/lukewilliamboswell?tab=repositories&q=platform-template&type=&language=&sort=
The {lang} host in the src/ directory produces a libhost.a (archive file, which contains a libhost.o object file) for the platform/main.roc targets:
targets: {
inputs_dir: "targets/",
x64mac: { inputs: ["libhost.a", app] },
arm64mac: { inputs: ["libhost.a", app] },
x64musl: { inputs: ["crt1.o", "libhost.a", app, "libc.a", "libzigc.a", "libcompiler_rt.a"] },
x64v1musl: { inputs: ["crt1.o", "libhost.a", app, "libc.a", "libzigc.a", "libcompiler_rt.a"] },
arm64musl: { inputs: ["crt1.o", "libhost.a", app, "libc.a", "libzigc.a", "libcompiler_rt.a"] },
arm64v1musl: { inputs: ["crt1.o", "libhost.a", app, "libc.a", "libzigc.a", "libcompiler_rt.a"] },
x64win: { inputs: ["host.lib", app] },
}
So you'll need to configure dotnet to produce an object or archive file; ie libhost.a that roc (or any other linker) can consume (depending on the target arch-OS).
The rest is sorting out any remaining linker errors, mismatching symbols etc. objdump can be useful to inspect the files.
You'll need to supply any other archive or object files that you may have dependencies for... libc.a if needed, crt1.o if producing an executable... etc.
Implement & export some memory allocation functions and allocate & initialize some memory for the roc host to reside in memory (whatever is suitable for your specific platform's requirements).
And then expanding the scope with your platform's requirements.
@Chander Ramesh here is an end to end example https://github.com/lukewilliamboswell/embed-roc-in-dotnet
It's not doing the glue for dotnet glue thing, it uses a Zig shim for the host and produces a dynamic library for C#
Hope this helps.
I forked @johan alley's template and adapted that a little
Last updated: Oct 15 2026 at 17:56 UTC