Assuming the Node.js scripting from .NET Core support has been put off until .NET Core settles down, that time has come!
What needs to be done on that front? I'm happy to help.
Hi Nick, thank you for the offer. @lstratman should be able to point you in the right direct.
@NickStrupat, everything in this post could change as I'm only just now starting to look at the Node.js scripting from CLR piece. I'm going to be getting the other half of Edge.js working with RC2 over the next few days and then hopefully should have some time to take a more in depth look at this. With all that being said, here goes:
A lot of the architecture for the existing "scripting Node.js from the CLR" will, stunningly enough, work pretty well with .NET Core. You can take a look at the existing code here. Basically, it relies on a compiled Node.js shared native library (node.dll) being in a certain directory structure, detects the process architecture (x86 vs. x64), calls the LoadLibrary kernel function to load the native library, and then calls a predefined hook function in that library to spin up V8 and launch the Edge.js init script. Now, .NET Core actually has incredibly good "associated native library support" where you have managed code that relies on calling into native code. It allows you to include versions of those native libraries for various architectures and operating systems either in the NuGet package or via dependencies for the various runtimes, and then .NET Core will take care of downloading the correct package for your OS and architecture and loading the native library into memory at runtime. Check out the native NuGet package for System.IO.Compression for Ubuntu for an example of this. So, all of the [DllImport]
s and function calls that we have now in EdgeJs.cs will continue to work in .NET Core, but we need to do some work with the NuGet package. So, preliminary tasks include:
node.dll
to the correct directory structure so that it's picked up by the aforementioned project.jsonsruntime
objects to the EdgeJs.cs project.json for win7-x86 and win7-x64 and dependencies
objects within them pointing to the aforementioned native project.json's[DllIImport]
in EdgeJs.cs for node.dll so that the function that it's looking for is something more cross-platform than "#925" (maybe just start
? You'll need to look at the exported functions in Dependency Walker or something)That's my initial brain dump, feel free to start looking at any of this stuff and reporting anything that goes wrong. I'll probably start on it myself later this week/early next week and can provide more detail at that point.
Great list @lstratman. Regarding the "#925" entry point (https://github.com/tjanczuk/edge/blob/master/src/double/dotnet/EdgeJs.cs#L51), note this has nothing to do with CLR - this is the entry point to the shared node.dll library, and is dependent on the version of Node.js that you are building for. Since Node has never been meant to be support shared library scenario in a first class way, these entry points are not stable between versions. It could be made nicer with a little wrapper or some extra code around node.dll, but I don't think this is necessarily that important in the grand scheme of things.
I need a MQTT client that supports client certificates for Windows IoI Core (WoA / RP3). This is for connecting to AWS IoT. I have updated the .Net M2Mqtt library to run on WoA / UWP (it works!), but would rather call into the AWS node.js library from my C# app. I don't need a nuget package for testing. I'm content with building the library in VS. I'm volunteering to test this scenario and share the results if Core development is far enough along to do so.
Posting a quick update on this. Started messing about with this a bit today and was able to get the Node.js native DLL referenced, loaded, and invoked successfully from .NET Core. So we're able to spin up the V8 runtime in a .NET Core process and run Node.js code, which is obviously huge. The sticking point is that edge_coreclr.node spins up the CLR itself, so when it's invoked, it actually creates another CLR domain inside the current process (crazy that it actually works), so it doesn't interact with the CLR instance that actually spun up the V8 runtime. Basically, I have to figure out how to, from native code, get hooks into an already-loaded CLR instead of spinning up the CLR from scratch and interacting with that. I'm sure it's possible, but I need to figure out how to do it.
I think @davidfowl may be able to provide a pointer for how to get a reference to a running app domain in coreclr, if it is possible.
How does .NET (edge_nativeclr.node) do this?
It's a mixed mode C++ assembly, so the VS compiler takes care of injecting whatever voodoo is necessary to find and interact with the CLR. Mixed mode assemblies are unfortunately not supported in .NET Core (for perfectly good and legitimate technical reasons). I believe that I can work around this by calling Marshal.GetFunctionPointerForDelegate() for all of the required delegate functions in CoreCLREmbedding and passing the function pointers to Node.js. I'll see if I can get that to work tomorrow.
OK, I got this working. The solution is a little dirty (Marshal.GetFunctionPointerForDelegate(), getting an unsafe pointer, and casting that to a long, then passing that as an environment variable. I know, I know, it's awful), but it's functional until someone wants to refactor it. The unit tests pass except for the Unicode one and that may have something to do with my underlying .NET string->Node.js string conversion logic and not anything to do with scripting Node.js from .NET. Right now this is Windows only until runtime NuGet packages are created for the other OSes: basically those NuGet packages will only contain node.dll/node.so/node.dylib and will be referenced from the Edge.js project.json in the runtimes
section.
Unfortunately, I have a big project at my actual day job that will be eating up most of my time over the next month or two so I'll be pivoting away from this and leaving the rest of the implementation work up to other interested parties. My code is in https://github.com/medicomp/edge in the double-netcore branch; @tjanczuk if you'd like me to create a PR for what I have, just let me know.
I'll take a look.
We're now a year on with this issue and I was wondering if there were any updates? Would be pretty awesome to host Node inside a .NETCore process.
Most helpful comment
We're now a year on with this issue and I was wondering if there were any updates? Would be pretty awesome to host Node inside a .NETCore process.