using System; using System.Runtime.InteropServices; namespace Python.Runtime.Platform { public enum MachineType { i386, x86_64, armv7l, armv8, aarch64, Other }; /// /// Operating system type as reported by Python. /// public enum OperatingSystemType { Windows, Darwin, Linux, Other } static class SystemInfo { public static MachineType GetMachineType() { return Runtime.IsWindows ? GetMachineType_Windows() : GetMachineType_Unix(); } public static string GetArchitecture() { return Runtime.IsWindows ? GetArchName_Windows() : GetArchName_Unix(); } public static OperatingSystemType GetSystemType() { if (Runtime.IsWindows) { return OperatingSystemType.Windows; } switch (PythonEngine.Platform) { case "linux": return OperatingSystemType.Linux; case "darwin": return OperatingSystemType.Darwin; default: return OperatingSystemType.Other; } } #region WINDOWS static string GetArchName_Windows() { // https://docs.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details return Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); } static MachineType GetMachineType_Windows() { if (Runtime.Is32Bit) { return MachineType.i386; } switch (GetArchName_Windows()) { case "AMD64": return MachineType.x86_64; case "ARM64": return MachineType.aarch64; default: return MachineType.Other; } } #endregion #region UNIX [StructLayout(LayoutKind.Sequential)] unsafe struct utsname_linux { const int NameLength = 65; /* Name of the implementation of the operating system. */ public fixed byte sysname[NameLength]; /* Name of this node on the network. */ public fixed byte nodename[NameLength]; /* Current release level of this implementation. */ public fixed byte release[NameLength]; /* Current version level of this release. */ public fixed byte version[NameLength]; /* Name of the hardware type the system is running on. */ public fixed byte machine[NameLength]; // GNU extension fixed byte domainname[NameLength]; /* NIS or YP domain name */ } [StructLayout(LayoutKind.Sequential)] unsafe struct utsname_darwin { const int NameLength = 256; /* Name of the implementation of the operating system. */ public fixed byte sysname[NameLength]; /* Name of this node on the network. */ public fixed byte nodename[NameLength]; /* Current release level of this implementation. */ public fixed byte release[NameLength]; /* Current version level of this release. */ public fixed byte version[NameLength]; /* Name of the hardware type the system is running on. */ public fixed byte machine[NameLength]; } [DllImport("libc")] static extern int uname(IntPtr buf); static unsafe string GetArchName_Unix() { switch (GetSystemType()) { case OperatingSystemType.Linux: { var buf = stackalloc utsname_linux[1]; if (uname((IntPtr)buf) != 0) { return null; } return Marshal.PtrToStringAnsi((IntPtr)buf->machine); } case OperatingSystemType.Darwin: { var buf = stackalloc utsname_darwin[1]; if (uname((IntPtr)buf) != 0) { return null; } return Marshal.PtrToStringAnsi((IntPtr)buf->machine); } default: return null; } } static unsafe MachineType GetMachineType_Unix() { switch (GetArchName_Unix()) { case "x86_64": case "em64t": return Runtime.Is32Bit ? MachineType.i386 : MachineType.x86_64; case "i386": case "i686": return MachineType.i386; case "armv7l": return MachineType.armv7l; case "armv8": return Runtime.Is32Bit ? MachineType.armv7l : MachineType.armv8; case "aarch64": return Runtime.Is32Bit ? MachineType.armv7l : MachineType.aarch64; default: return MachineType.Other; } } #endregion } }