From b8de1e563a6e2f955a7dd3c277c0798ff60b9fda Mon Sep 17 00:00:00 2001 From: Kuan Bartel Date: Thu, 12 Mar 2015 18:02:45 +0900 Subject: [PATCH] Changed behaviour to only attempt to load the library if it is found within an architecture specific subfolder. If not found then LoadLibrary will return false allowing the normal P/Invoke load behaviour as P/Invoke searches in a slightly different order to the dlopen() and LoadLibrary() functions. For Unix based OS changed to only supporting x86 and amd64 as I haven't found a reliable way to detect the architecture. MKL only supports x86 and amd64 anyway so it isn't currently a problem but could be for other native providers which support other architectures. --- .../Providers/NativeProviderLoader.cs | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/Numerics/Providers/NativeProviderLoader.cs b/src/Numerics/Providers/NativeProviderLoader.cs index 04cd6775..fdcfe3b0 100644 --- a/src/Numerics/Providers/NativeProviderLoader.cs +++ b/src/Numerics/Providers/NativeProviderLoader.cs @@ -49,7 +49,7 @@ namespace MathNet.Numerics.Providers {"x86", "x86"}, {"AMD64", "amd64"}, {"IA64", "ia64"}, - {"ARM", "arm"} // Is there an ARM64? + {"ARM", "arm"} }, true); /// @@ -73,10 +73,19 @@ namespace MathNet.Numerics.Providers { if (string.IsNullOrEmpty(_ArchDirectory)) { - string architecture = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); - if (!Environment.Is64BitProcess && Environment.Is64BitOperatingSystem) + string architecture; + if (IsUnix) { - architecture = string.Equals(architecture, "ARM", StringComparison.OrdinalIgnoreCase) ? "ARM" : "x86"; + // Only support x86 and amd64 on Unix as there isn't a reliable way to detect the architecture + architecture = Environment.Is64BitProcess ? "AMD64" : "x86"; + } + else + { + architecture = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); + if (!Environment.Is64BitProcess && string.Equals(architecture, "AMD64", StringComparison.OrdinalIgnoreCase)) + { + architecture = "x86"; + } } // Fallback to using the architecture name if unknown @@ -98,7 +107,8 @@ namespace MathNet.Numerics.Providers } /// - /// If the last native library failed to load then gets the corresponding exception which occurred or null if the library was successfully loaded. + /// If the last native library failed to load then gets the corresponding exception + /// which occurred or null if the library was successfully loaded. /// public static Exception LastException { get; private set; } @@ -119,20 +129,17 @@ namespace MathNet.Numerics.Providers if (NativeHandles.TryGetValue(fileName, out libraryHandle)) return true; - string path = null; - if (!IsUnix) - { - path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ArchDirectory, fileName); - } - if (string.IsNullOrEmpty(path) || !File.Exists(path)) + string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ArchDirectory, fileName); + + if (string.IsNullOrEmpty(ArchDirectory) || !File.Exists(path)) { - // Even if we haven't found the library try and load it using LoadLibrary's normal - // search rules by just using the filename without a path - path = fileName; + // If the library isn't found within an architecture specific folder then return false + // to allow normal P/Invoke searching behaviour when the library is called + return false; } // If successful this will return a handle to the library - libraryHandle = IsUnix ? UnixLoader.LoadLibrary(path) : UnixLoader.LoadLibrary(path); + libraryHandle = IsUnix ? UnixLoader.LoadLibrary(path) : WindowsLoader.LoadLibrary(path); if (libraryHandle == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); @@ -168,7 +175,7 @@ namespace MathNet.Numerics.Providers const int RTLD_NOW = 2; - [DllImport("libdl.so")] + [DllImport("libdl.so", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr dlopen(String fileName, int flags); } }