From 483f1922fda4b477b6dfa549b65e068183c7700c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 24 Mar 2021 22:05:02 -0700 Subject: [PATCH] try libdl.so.2 on Linux before libdl.so also refactored LibraryLoader to share code between Linux and Mac fixes https://github.com/pythonnet/pythonnet/issues/1422 --- src/runtime/platform/LibDL.cs | 109 ++++++++++++++++++++++++++ src/runtime/platform/LibraryLoader.cs | 104 +++--------------------- 2 files changed, 121 insertions(+), 92 deletions(-) create mode 100644 src/runtime/platform/LibDL.cs diff --git a/src/runtime/platform/LibDL.cs b/src/runtime/platform/LibDL.cs new file mode 100644 index 000000000..3bf2a2057 --- /dev/null +++ b/src/runtime/platform/LibDL.cs @@ -0,0 +1,109 @@ +#pragma warning disable IDE1006 // Naming Styles (interface for native functions) +using System; +using System.Runtime.InteropServices; + +namespace Python.Runtime.Platform +{ + interface ILibDL + { + IntPtr dlopen(string fileName, int flags); + IntPtr dlsym(IntPtr handle, string symbol); + int dlclose(IntPtr handle); + IntPtr dlerror(); + + int RTLD_NOW { get; } + int RTLD_GLOBAL { get; } + IntPtr RTLD_DEFAULT { get; } + } + + class LinuxLibDL : ILibDL + { + private const string NativeDll = "libdl.so"; + + public int RTLD_NOW => 0x2; + public int RTLD_GLOBAL => 0x100; + public IntPtr RTLD_DEFAULT => IntPtr.Zero; + + public static ILibDL GetInstance() + { + try + { + ILibDL libdl2 = new LinuxLibDL2(); + // call dlerror to ensure library is resolved + libdl2.dlerror(); + return libdl2; + } catch (DllNotFoundException) + { + return new LinuxLibDL(); + } + } + + IntPtr ILibDL.dlopen(string fileName, int flags) => dlopen(fileName, flags); + IntPtr ILibDL.dlsym(IntPtr handle, string symbol) => dlsym(handle, symbol); + int ILibDL.dlclose(IntPtr handle) => dlclose(handle); + IntPtr ILibDL.dlerror() => dlerror(); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlopen(string fileName, int flags); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern int dlclose(IntPtr handle); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr dlerror(); + } + + class LinuxLibDL2 : ILibDL + { + private const string NativeDll = "libdl.so.2"; + + public int RTLD_NOW => 0x2; + public int RTLD_GLOBAL => 0x100; + public IntPtr RTLD_DEFAULT => IntPtr.Zero; + + IntPtr ILibDL.dlopen(string fileName, int flags) => dlopen(fileName, flags); + IntPtr ILibDL.dlsym(IntPtr handle, string symbol) => dlsym(handle, symbol); + int ILibDL.dlclose(IntPtr handle) => dlclose(handle); + IntPtr ILibDL.dlerror() => dlerror(); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlopen(string fileName, int flags); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern int dlclose(IntPtr handle); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr dlerror(); + } + + class MacLibDL : ILibDL + { + public int RTLD_NOW => 0x2; + public int RTLD_GLOBAL => 0x8; + const string NativeDll = "/usr/lib/libSystem.dylib"; + public IntPtr RTLD_DEFAULT => new(-2); + + IntPtr ILibDL.dlopen(string fileName, int flags) => dlopen(fileName, flags); + IntPtr ILibDL.dlsym(IntPtr handle, string symbol) => dlsym(handle, symbol); + int ILibDL.dlclose(IntPtr handle) => dlclose(handle); + IntPtr ILibDL.dlerror() => dlerror(); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlopen(string fileName, int flags); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern int dlclose(IntPtr handle); + + [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr dlerror(); + } +} diff --git a/src/runtime/platform/LibraryLoader.cs b/src/runtime/platform/LibraryLoader.cs index 099b9d6cd..e361f87e4 100644 --- a/src/runtime/platform/LibraryLoader.cs +++ b/src/runtime/platform/LibraryLoader.cs @@ -28,9 +28,9 @@ public static ILibraryLoader Instance if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) _instance = new WindowsLoader(); else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - _instance = new LinuxLoader(); + _instance = new PosixLoader(LinuxLibDL.GetInstance()); else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - _instance = new DarwinLoader(); + _instance = new PosixLoader(new MacLibDL()); else throw new PlatformNotSupportedException( "This operating system is not supported" @@ -42,87 +42,19 @@ public static ILibraryLoader Instance } } - class LinuxLoader : ILibraryLoader + class PosixLoader : ILibraryLoader { - private static int RTLD_NOW = 0x2; - private static int RTLD_GLOBAL = 0x100; - private static IntPtr RTLD_DEFAULT = IntPtr.Zero; - private const string NativeDll = "libdl.so"; + private readonly ILibDL libDL; - public IntPtr Load(string dllToLoad) - { - ClearError(); - var res = dlopen(dllToLoad, RTLD_NOW | RTLD_GLOBAL); - if (res == IntPtr.Zero) - { - var err = GetError(); - throw new DllNotFoundException($"Could not load {dllToLoad} with flags RTLD_NOW | RTLD_GLOBAL: {err}"); - } - - return res; - } - - public void Free(IntPtr handle) - { - dlclose(handle); - } - - public IntPtr GetFunction(IntPtr dllHandle, string name) - { - // look in the exe if dllHandle is NULL - if (dllHandle == IntPtr.Zero) - { - dllHandle = RTLD_DEFAULT; - } - - ClearError(); - IntPtr res = dlsym(dllHandle, name); - if (res == IntPtr.Zero) - { - var err = GetError(); - throw new MissingMethodException($"Failed to load symbol {name}: {err}"); - } - return res; - } - - void ClearError() + public PosixLoader(ILibDL libDL) { - dlerror(); - } - - string GetError() - { - var res = dlerror(); - if (res != IntPtr.Zero) - return Marshal.PtrToStringAnsi(res); - else - return null; + this.libDL = libDL ?? throw new ArgumentNullException(nameof(libDL)); } - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlopen(string fileName, int flags); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - private static extern IntPtr dlsym(IntPtr handle, string symbol); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern int dlclose(IntPtr handle); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr dlerror(); - } - - class DarwinLoader : ILibraryLoader - { - private static int RTLD_NOW = 0x2; - private static int RTLD_GLOBAL = 0x8; - private const string NativeDll = "/usr/lib/libSystem.dylib"; - private static IntPtr RTLD_DEFAULT = new IntPtr(-2); - public IntPtr Load(string dllToLoad) { ClearError(); - var res = dlopen(dllToLoad, RTLD_NOW | RTLD_GLOBAL); + var res = libDL.dlopen(dllToLoad, libDL.RTLD_NOW | libDL.RTLD_GLOBAL); if (res == IntPtr.Zero) { var err = GetError(); @@ -134,7 +66,7 @@ public IntPtr Load(string dllToLoad) public void Free(IntPtr handle) { - dlclose(handle); + libDL.dlclose(handle); } public IntPtr GetFunction(IntPtr dllHandle, string name) @@ -142,11 +74,11 @@ public IntPtr GetFunction(IntPtr dllHandle, string name) // look in the exe if dllHandle is NULL if (dllHandle == IntPtr.Zero) { - dllHandle = RTLD_DEFAULT; + dllHandle = libDL.RTLD_DEFAULT; } ClearError(); - IntPtr res = dlsym(dllHandle, name); + IntPtr res = libDL.dlsym(dllHandle, name); if (res == IntPtr.Zero) { var err = GetError(); @@ -157,29 +89,17 @@ public IntPtr GetFunction(IntPtr dllHandle, string name) void ClearError() { - dlerror(); + libDL.dlerror(); } string GetError() { - var res = dlerror(); + var res = libDL.dlerror(); if (res != IntPtr.Zero) return Marshal.PtrToStringAnsi(res); else return null; } - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlopen(String fileName, int flags); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - private static extern IntPtr dlsym(IntPtr handle, String symbol); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern int dlclose(IntPtr handle); - - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr dlerror(); } class WindowsLoader : ILibraryLoader pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy