Edit: Using the tool "dllexport" (https://github.com/3F/DllExport), you can create a .NET DLL that exports a function that is callable from C/C++ code. Just LoadLibrary and GetProcAddress.
Edit: Using the tool "dllexport" (https://github.com/3F/DllExport), you can create a .NET DLL that exports a function that is callable from C/C++ code. Just LoadLibrary and GetProcAddress.
The DLL links to MSCOREE.DLL. When loaded into a process, the DLL can initialize the .NET runtime when necessary. The DLL's entry point is a jump to _CorDllMain within MSCOREE.DLL, which takes care of loading and initializing .NET if it hasn't been done before.
As for how it manages to initialize .NET from within DllMain (you're under DLL loader lock at this point), I don't know. It has to somehow get out of loader lock at some point before it loads a bunch of DLLs.
Thanks to NativeAOT, though, it seems that you can do this kind of stuff without extra dependencies which is great too!
And exporting to WASM works nearly identically to DllExport.
I used that to shift all the heavy lifting to .NET 9 AOT compiled to WASM in a fun little side project I've been working on: https://evo.ryanpeden.com
I plan to put the source on GitHub shortly so others can use it as an example. Just need to clean things up a little first.