using System;using System.ComponentModel;using System.Diagnostics;using System.Linq;using System.Runtime.InteropServices;namespace Python.Runtime.Platform{interface ILibraryLoader{IntPtr Load(string? dllToLoad);IntPtr GetFunction(IntPtr hModule, string procedureName);void Free(IntPtr hModule);}static class LibraryLoader{static ILibraryLoader? _instance = null;public static ILibraryLoader Instance{get{if (_instance == null){if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))_instance = new WindowsLoader();else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))_instance = new PosixLoader(LinuxLibDL.GetInstance());else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))_instance = new PosixLoader(new MacLibDL());elsethrow new PlatformNotSupportedException("This operating system is not supported");}return _instance;}}}class PosixLoader : ILibraryLoader{private readonly ILibDL libDL;public PosixLoader(ILibDL libDL){this.libDL = libDL ?? throw new ArgumentNullException(nameof(libDL));}public IntPtr Load(string? dllToLoad){ClearError();var res = libDL.dlopen(dllToLoad, libDL.RTLD_NOW | libDL.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){libDL.dlclose(handle);}public IntPtr GetFunction(IntPtr dllHandle, string name){// look in the exe if dllHandle is NULLif (dllHandle == IntPtr.Zero){dllHandle = libDL.RTLD_DEFAULT;}ClearError();IntPtr res = libDL.dlsym(dllHandle, name);if (res == IntPtr.Zero){var err = GetError();throw new MissingMethodException($"Failed to load symbol {name}: {err}");}return res;}void ClearError(){libDL.dlerror();}string? GetError(){var res = libDL.dlerror();if (res != IntPtr.Zero)return Marshal.PtrToStringAnsi(res);elsereturn null;}}class WindowsLoader : ILibraryLoader{private const string NativeDll = "kernel32.dll";public IntPtr Load(string? dllToLoad){if (dllToLoad is null) return IntPtr.Zero;var res = WindowsLoader.LoadLibrary(dllToLoad);if (res == IntPtr.Zero)throw new DllNotFoundException($"Could not load {dllToLoad}.", new Win32Exception());return res;}public IntPtr GetFunction(IntPtr hModule, string procedureName){if (hModule == IntPtr.Zero){foreach(var module in GetAllModules()){var func = GetProcAddress(module, procedureName);if (func != IntPtr.Zero) return func;}}var res = WindowsLoader.GetProcAddress(hModule, procedureName);if (res == IntPtr.Zero)throw new MissingMethodException($"Failed to load symbol {procedureName}.", new Win32Exception());return res;}public void Free(IntPtr hModule) => WindowsLoader.FreeLibrary(hModule);static IntPtr[] GetAllModules(){using var self = Process.GetCurrentProcess();uint bytes = 0;var result = new IntPtr[0];if (!EnumProcessModules(self.Handle, result, bytes, out var needsBytes))throw new Win32Exception();while (bytes < needsBytes){bytes = needsBytes;result = new IntPtr[bytes / IntPtr.Size];if (!EnumProcessModules(self.Handle, result, bytes, out needsBytes))throw new Win32Exception();}return result.Take((int)(needsBytes / IntPtr.Size)).ToArray();}[DllImport(NativeDll, SetLastError = true)]static extern IntPtr LoadLibrary(string dllToLoad);[DllImport(NativeDll, SetLastError = true)]static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);[DllImport(NativeDll)]static extern bool FreeLibrary(IntPtr hModule);[DllImport("Psapi.dll", SetLastError = true)]static extern bool EnumProcessModules(IntPtr hProcess, [In, Out] IntPtr[] lphModule, uint lphModuleByteCount, out uint byteCountNeeded);}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。