| File: Utility\NativeLibrary.cs | Web Access |
| Project: src\test\Microsoft.ML.TestFrameworkCommon\Microsoft.ML.TestFrameworkCommon.csproj (Microsoft.ML.TestFrameworkCommon) |
// Taken from https://github.com/mellinoe/nativelibraryloader/blob/586f9738ff12688df8f0662027da8c319aee3841/NativeLibraryLoader/NativeLibrary.cs using System; using System.Runtime.InteropServices; namespace Microsoft.ML.TestFrameworkCommon.Utility { /// <summary> /// Represents a native shared library opened by the operating system. /// This type can be used to load native function pointers by name. /// </summary> public class NativeLibrary : IDisposable { private static readonly LibraryLoader _platformDefaultLoader = LibraryLoader.GetPlatformDefaultLoader(); private readonly LibraryLoader _loader; public static bool NativeLibraryExists(string name) { NativeLibrary nativeLibrary = default; string extension = default; string prefix = "lib"; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) extension = ".dylib"; else if (Environment.OSVersion.Platform == PlatformID.Unix) extension = ".so"; else extension = ".dll"; try { // Try the native name as is. nativeLibrary = new NativeLibrary(name + extension); return true; } catch { // If that didn't load, dispose of the first attempt and try appending lib in front try { nativeLibrary?.Dispose(); nativeLibrary = new NativeLibrary(prefix + name + extension); return true; } catch { // If that didn't load, dispose of the first attempt and try appending lib_ in front try { nativeLibrary?.Dispose(); nativeLibrary = new NativeLibrary(prefix + "_" + name + extension); return true; } catch { return false; } } } finally { nativeLibrary?.Dispose(); } } /// <summary> /// The operating system handle of the loaded library. /// </summary> public IntPtr Handle { get; } /// <summary> /// Constructs a new NativeLibrary using the platform's default library loader. /// </summary> /// <param name="name">The name of the library to load.</param> public NativeLibrary(string name) : this(name, _platformDefaultLoader, PathResolver.Default) { } /// <summary> /// Constructs a new NativeLibrary using the platform's default library loader. /// </summary> /// <param name="names">An ordered list of names to attempt to load.</param> public NativeLibrary(string[] names) : this(names, _platformDefaultLoader, PathResolver.Default) { } /// <summary> /// Constructs a new NativeLibrary using the specified library loader. /// </summary> /// <param name="name">The name of the library to load.</param> /// <param name="loader">The loader used to open and close the library, and to load function pointers.</param> public NativeLibrary(string name, LibraryLoader loader) : this(name, loader, PathResolver.Default) { } /// <summary> /// Constructs a new NativeLibrary using the specified library loader. /// </summary> /// <param name="names">An ordered list of names to attempt to load.</param> /// <param name="loader">The loader used to open and close the library, and to load function pointers.</param> public NativeLibrary(string[] names, LibraryLoader loader) : this(names, loader, PathResolver.Default) { } /// <summary> /// Constructs a new NativeLibrary using the specified library loader. /// </summary> /// <param name="name">The name of the library to load.</param> /// <param name="loader">The loader used to open and close the library, and to load function pointers.</param> /// <param name="pathResolver">The path resolver, used to identify possible load targets for the library.</param> public NativeLibrary(string name, LibraryLoader loader, PathResolver pathResolver) { _loader = loader; Handle = _loader.LoadNativeLibrary(name, pathResolver); } /// <summary> /// Constructs a new NativeLibrary using the specified library loader. /// </summary> /// <param name="names">An ordered list of names to attempt to load.</param> /// <param name="loader">The loader used to open and close the library, and to load function pointers.</param> /// <param name="pathResolver">The path resolver, used to identify possible load targets for the library.</param> public NativeLibrary(string[] names, LibraryLoader loader, PathResolver pathResolver) { _loader = loader; Handle = _loader.LoadNativeLibrary(names, pathResolver); } /// <summary> /// Loads a function whose signature matches the given delegate type's signature. /// </summary> /// <typeparam name="T">The type of delegate to return.</typeparam> /// <param name="name">The name of the native export.</param> /// <returns>A delegate wrapping the native function.</returns> /// <exception cref="InvalidOperationException">Thrown when no function with the given name /// is exported from the native library.</exception> public T LoadFunction<T>(string name) { IntPtr functionPtr = _loader.LoadFunctionPointer(Handle, name); if (functionPtr == IntPtr.Zero) { throw new InvalidOperationException($"No function was found with the name {name}."); } return Marshal.GetDelegateForFunctionPointer<T>(functionPtr); } /// <summary> /// Loads a function pointer with the given name. /// </summary> /// <param name="name">The name of the native export.</param> /// <returns>A function pointer for the given name, or 0 if no function with that name exists.</returns> public IntPtr LoadFunction(string name) { return _loader.LoadFunctionPointer(Handle, name); } /// <summary> /// Frees the native library. Function pointers retrieved from this library will be void. /// </summary> public void Dispose() { _loader.FreeNativeLibrary(Handle); } } }