From 4d43b54d8b5dca6af496fe9d4213452659c848af Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 29 Nov 2020 18:37:01 -0800 Subject: [PATCH] detect the size of wchar_t (aka Runtime.UCS) at runtime using PyUnicode_GetMax --- .editorconfig | 4 +++ CHANGELOG.md | 1 + setup.py | 6 ----- src/runtime/Python.Runtime.15.csproj | 25 +++++++++--------- src/runtime/Python.Runtime.csproj | 16 ++++++------ src/runtime/runtime.cs | 39 +++------------------------- 6 files changed, 29 insertions(+), 62 deletions(-) diff --git a/.editorconfig b/.editorconfig index d64f74bc1..7b07446e3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -34,6 +34,10 @@ csharp_new_line_before_finally = true [*.sln] indent_style = tab +[*.csproj] +charset = utf-8 +insert_final_newline = true + # bumpversion reformats itself after every bump [.bumpversion.cfg] trim_trailing_whitespace = false diff --git a/CHANGELOG.md b/CHANGELOG.md index 13838e0ff..4c3f389d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Changed - Drop support for Python 2, 3.4, and 3.5 +- `wchar_t` size aka `Runtime.UCS` is now determined at runtime - `clr.AddReference` may now throw errors besides `FileNotFoundException`, that provide more details about the cause of the failure - `clr.AddReference` no longer adds ".dll" implicitly diff --git a/setup.py b/setup.py index 9d8f8de3a..0b352b8af 100644 --- a/setup.py +++ b/setup.py @@ -251,14 +251,8 @@ def build_extension(self, ext): if not os.path.exists(dest_dir): os.makedirs(dest_dir) - # Up to Python 3.2 sys.maxunicode is used to determine the size of - # Py_UNICODE, but from 3.3 onwards Py_UNICODE is a typedef of wchar_t. - import ctypes - unicode_width = ctypes.sizeof(ctypes.c_wchar) - defines = [ "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR), - "UCS{0}".format(unicode_width), ] if CONFIG == "Debug": diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 4ca8140e9..d530fd5e4 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -49,9 +49,8 @@ $(PYTHONNET_PY3_VERSION) PYTHON38 $(PYTHONNET_WIN_DEFINE_CONSTANTS) - UCS2 $(PYTHONNET_MONO_DEFINE_CONSTANTS) - UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC + MONO_LINUX;PYTHON_WITH_PYMALLOC $(PYTHONNET_INTEROP_FILE) @@ -143,20 +142,20 @@ - - - TextTemplatingFileGenerator - intern_.cs - + + + TextTemplatingFileGenerator + intern_.cs + - - - True - True - intern_.tt - + + + True + True + intern_.tt + diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 418620136..b516d89db 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -29,46 +29,46 @@ x64 --> - PYTHON2;PYTHON27;UCS4 + PYTHON2;PYTHON27 true pdbonly - PYTHON3;PYTHON38;UCS4 + PYTHON3;PYTHON38 true pdbonly true - PYTHON2;PYTHON27;UCS4;TRACE;DEBUG + PYTHON2;PYTHON27;TRACE;DEBUG false full true - PYTHON3;PYTHON38;UCS4;TRACE;DEBUG + PYTHON3;PYTHON38;TRACE;DEBUG false full - PYTHON2;PYTHON27;UCS2 + PYTHON2;PYTHON27 true pdbonly - PYTHON3;PYTHON38;UCS2 + PYTHON3;PYTHON38 true pdbonly true - PYTHON2;PYTHON27;UCS2;TRACE;DEBUG + PYTHON2;PYTHON27;TRACE;DEBUG false full true - PYTHON3;PYTHON38;UCS2;TRACE;DEBUG + PYTHON3;PYTHON38;TRACE;DEBUG false full diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 10aa165c8..ece36513d 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -18,31 +18,8 @@ namespace Python.Runtime /// public class Runtime { - // C# compiler copies constants to the assemblies that references this library. - // We needs to replace all public constants to static readonly fields to allow - // binary substitution of different Python.Runtime.dll builds in a target application. - public static int UCS => _UCS; - -#if UCS4 - internal const int _UCS = 4; - - /// - /// EntryPoint to be used in DllImport to map to correct Unicode - /// methods prior to PEP393. Only used for PY27. - /// - private const string PyUnicodeEntryPoint = "PyUnicodeUCS4_"; -#elif UCS2 - internal const int _UCS = 2; - - /// - /// EntryPoint to be used in DllImport to map to correct Unicode - /// methods prior to PEP393. Only used for PY27. - /// - private const string PyUnicodeEntryPoint = "PyUnicodeUCS2_"; -#else -#error You must define either UCS2 or UCS4! -#endif + internal static readonly int _UCS = PyUnicode_GetMax() <= 0xFFFF ? 2 : 4; #if PYTHON36 const string _minor = "6"; @@ -1537,17 +1514,6 @@ internal static IntPtr PyBytes_AS_STRING(IntPtr ob) return ob + BytesOffset.ob_sval; } - internal static IntPtr PyString_FromStringAndSize(string value, long size) - { - return _PyString_FromStringAndSize(value, new IntPtr(size)); - } - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_FromStringAndSize")] - internal static extern IntPtr _PyString_FromStringAndSize( - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, - IntPtr size - ); internal static IntPtr PyUnicode_FromStringAndSize(IntPtr value, long size) { @@ -1588,6 +1554,9 @@ internal static IntPtr PyUnicode_FromUnicode(string s, long size) return PyUnicode_FromKindAndData(_UCS, s, size); } + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyUnicode_GetMax(); + internal static long PyUnicode_GetSize(IntPtr ob) { return (long)_PyUnicode_GetSize(ob);