-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Importing node-api-dotnet
into node into a dotnet app
#330
Comments
This is an interesting scenario, but not something we have tried to enable so far.
This fails because That might be possible to fix, but then there would be another problem: it will try to initialize the .NET runtime, which I think will fail because .NET is already loaded in the current process. (And you don't want it to use a separate instance of the .NET runtime anyway.) Instead of that, I think it should be possible to initialize |
Thanks Jason. This seems to work with the system classes, is it what you had in mind? NodejsPlatform platform = new("libnode.dll");
NodejsEnvironment env = platform.CreateEnvironment();
await env.RunAsync(async () =>
{
JSObject exports = [];
JSValue.Global.SetProperty("dotnet", exports);
ManagedHost mh = new ManagedHost(exports);
JSValue.RunScript($"dotnet.System.Console.WriteLine(\"tada\")");
}); How do I go about importing a third party dll into this? ( |
To load an external dll "correctly", the following seemed to work:
private static void LoadDefaultDotNetTypes(NodejsEnvironment env)
{
ManualResetEventSlim mre = new ManualResetEventSlim();
env.RunAsync(async () =>
{
try
{
JSObject exports = [];
JSValue.Global.SetProperty("dotnet", exports);
ManagedHost managedHost = new ManagedHost(exports);
FieldInfo field = typeof(ManagedHost).GetField("_loadContext", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(managedHost, AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()));
LoadDotNetLibrary(managedHost, typeof(MyLib).Assembly.Location);
}
finally
{
mre.Set();
}
});
mre.Wait();
} and private static void LoadDotNetLibrary(ManagedHost managedHost, string libFullPath)
{
MethodInfo method = typeof(ManagedHost).GetMethod("LoadAssembly", BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(managedHost, new object[] { libFullPath, false });
} Though the load context should probably be assigned before running the constructor? |
After playing with #340 for a while, I realise I have been a little silly. The dll is already loaded into the dotnet context, so it doesn't need to be loaded again by the ManagedHost. Here's a little hack that works for me, which does the type exporting functionality of the ManagedHost without the assembly loading. // Set JSMarshaller.Current because it is usually set by ManagedHost.
typeof(JSMarshaller)
.GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, new JSMarshaller()
{
AutoCamelCase = false
});
JSObject managedTypes = (JSObject)JSValue.CreateObject();
JSValue.Global.SetProperty("dotnet", managedTypes);
TypeExporter te = new TypeExporter(JSMarshaller.Current, managedTypes);
te.ExportAssemblyTypes(typeof(MyClass).Assembly);
te.ExportType(typeof(MyClass)); So, finally:
|
Certainly there can be a better way. I plan to improve the API to make this scenario easier, but I have not had time yet to focus on this.
Currently
Yes, I was thinking of adding that after the discussion in #346 where there was a need to call it with a |
From some testing my understanding is that I need If so, this becomes a non-issue as |
The use case here is to create a runtime "script editor" that uses javascript/typescript as the language.
So the goal is:
I'm having issues calling the javascript import of node-api-dotnet when it's running inside the host process. Here's a reproducible example, where the
TEST_MS
flag just makes sure it does work with the simplems
package.The exception I get here is:
Which is the same when using
await env.ImportAsync("C:/node_modules/node-api-dotnet/net8.0", null, true);
It did occur to me that the
Microsoft.JavaScript.NodeApi.dll
exists in both the dotnet project and the node module here. Any ideas on how to resolve this?The text was updated successfully, but these errors were encountered: