- 
                Notifications
    
You must be signed in to change notification settings  - Fork 73
 
Use high-level library load API #217
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
base: main
Are you sure you want to change the base?
Changes from 15 commits
d765df3
              d877e54
              1dd3250
              e6fa1c6
              61c787a
              ca3313c
              06121a9
              f751f2b
              c9b67b6
              2497f24
              f24f6d2
              009a09f
              e6e1b38
              16e53be
              f3b8f1e
              11cfb01
              678e3ba
              5b0e460
              11a708e
              0260cbd
              bc1091c
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -4,6 +4,8 @@ | |
| #if !NET7_0_OR_GREATER | ||
| 
     | 
||
| using System; | ||
| using System.IO; | ||
| using System.Reflection; | ||
| using System.Runtime.InteropServices; | ||
| #if !NETFRAMEWORK | ||
| using SysNativeLibrary = System.Runtime.InteropServices.NativeLibrary; | ||
| 
          
            
          
           | 
    @@ -50,6 +52,25 @@ public static nint Load(string libraryName) | |
| #endif | ||
| } | ||
| 
     | 
||
| /// <summary> | ||
| /// Loads a native library using the high-level API. | ||
| /// </summary> | ||
| /// <param name="libraryName">The name of the native library to be loaded.</param> | ||
| /// <param name="assembly">The assembly loading the native library.</param> | ||
| /// <param name="searchPath">The search path.</param> | ||
| /// <returns>The OS handle for the loaded native library.</returns> | ||
| public static nint Load(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) | ||
| { | ||
| #if NETFRAMEWORK | ||
| string libraryPath = FindLibrary(libraryName, assembly) | ||
| ?? throw new ArgumentNullException(nameof(libraryName)); | ||
| 
     | 
||
| return LoadLibrary(libraryPath); | ||
| #else | ||
| return SysNativeLibrary.Load(libraryName, assembly, searchPath); | ||
| #endif | ||
| } | ||
| 
     | 
||
| /// <summary> | ||
| /// Gets the address of an exported symbol. | ||
| /// </summary> | ||
| 
        
          
        
         | 
    @@ -75,6 +96,72 @@ public static bool TryGetExport(nint handle, string name, out nint procAddress) | |
| #endif | ||
| } | ||
| 
     | 
||
| /// <summary> | ||
| /// Searches various well-known paths for a library and returns the first result. | ||
| /// </summary> | ||
| /// <param name="libraryName">Name of the library to search for.</param> | ||
| /// <param name="assembly">Assembly to search relative from.</param> | ||
| /// <returns>Library path if found, otherwise false.</returns> | ||
| private static string? FindLibrary(string libraryName, Assembly assembly) | ||
| { | ||
| if (File.Exists(libraryName)) | ||
                
       | 
||
| { | ||
| return Path.GetFullPath(libraryName); | ||
| } | ||
| 
     | 
||
| string[] tryLibraryNames; | ||
| 
     | 
||
| if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
| { | ||
| tryLibraryNames = | ||
| [ | ||
| libraryName, | ||
| $"{libraryName}.dll" | ||
| ]; | ||
| } | ||
| else | ||
| { | ||
| string libraryExtension = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) | ||
| ? "dylib" | ||
| : "so"; | ||
| 
     | 
||
| tryLibraryNames = | ||
| [ | ||
| libraryName, | ||
| $"lib{libraryName}", | ||
| $"{libraryName}.{libraryExtension}", | ||
| $"lib{libraryName}.{libraryExtension}" | ||
| ]; | ||
| } | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This else block is not needed. This method is only used with .NET Framework 4.x, which only runs on Windows, so there is no need to consider other operating systems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about Mono here - not sure if it's a target you might want to support though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're not attempting to support Mono. There are several places in code already that assume anything within   | 
||
| 
     | 
||
| string?[] tryDirectories = | ||
| [ | ||
| Path.GetDirectoryName(assembly.Location), | ||
| Environment.CurrentDirectory, | ||
                
       | 
||
| Environment.SystemDirectory, | ||
| ]; | ||
| 
     | 
||
| foreach (string? tryDirectory in tryDirectories) | ||
| { | ||
| if (tryDirectory == null) | ||
| { | ||
| continue; | ||
| } | ||
| 
     | 
||
| foreach (string tryLibraryName in tryLibraryNames) | ||
| { | ||
| string tryLibraryPath = Path.Combine(tryDirectory, tryLibraryName); | ||
| 
     | 
||
| if (File.Exists(tryLibraryPath)) | ||
| { | ||
| return tryLibraryPath; | ||
| } | ||
| } | ||
| } | ||
| 
     | 
||
| return null; | ||
| } | ||
| 
     | 
||
| #pragma warning disable CA2101 // Specify marshaling for P/Invoke string arguments | ||
| 
     | 
||
| [DllImport("kernel32")] | ||
| 
          
            
          
           | 
    ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -2,6 +2,7 @@ | |
| // Licensed under the MIT License. | ||
| 
     | 
||
| using System; | ||
| using System.Reflection; | ||
| using System.Runtime.InteropServices; | ||
| 
     | 
||
| namespace Microsoft.JavaScript.NodeApi.Runtime; | ||
| 
        
          
        
         | 
    @@ -25,23 +26,30 @@ public sealed class NodejsPlatform : IDisposable | |
| /// <summary> | ||
| /// Initializes the Node.js platform. | ||
| /// </summary> | ||
| /// <param name="libnodePath">Path to the `libnode` shared library, including extension.</param> | ||
| /// <param name="libnode"> | ||
| /// Name of the `libnode` shared library. | ||
| /// Has to be a full file path when using .NET Framework. | ||
| /// </param> | ||
| /// <param name="args">Optional platform arguments.</param> | ||
| /// <exception cref="InvalidOperationException">A Node.js platform instance has already been | ||
| /// loaded in the current process.</exception> | ||
| public NodejsPlatform( | ||
| string libnodePath, | ||
| string libnode, | ||
| string[]? args = null) | ||
| { | ||
| if (string.IsNullOrEmpty(libnodePath)) throw new ArgumentNullException(nameof(libnodePath)); | ||
| 
     | 
||
| if (Current != null) | ||
| { | ||
| throw new InvalidOperationException( | ||
| "Only one Node.js platform instance per process is allowed."); | ||
| } | ||
| 
     | 
||
| nint libnodeHandle = NativeLibrary.Load(libnodePath); | ||
| var entryAssembly = Assembly.GetAssembly(typeof(NodejsPlatform)); | ||
| 
     | 
||
| nint libnodeHandle = | ||
| entryAssembly != null | ||
| ? NativeLibrary.Load(libnode, entryAssembly!, null) | ||
                
       | 
||
| : NativeLibrary.Load(libnode); | ||
| 
     | 
||
| Runtime = new NodejsRuntime(libnodeHandle); | ||
| 
     | 
||
| Runtime.CreatePlatform(args, (error) => Console.WriteLine(error), out _platform) | ||
| 
          
            
          
           | 
    ||
Uh oh!
There was an error while loading. Please reload this page.