diff --git a/Lib/test/test_ctypes/test_numbers.py b/Lib/test/test_ctypes/test_numbers.py index b7df08f6079cd3..26f7a032c3974c 100644 --- a/Lib/test/test_ctypes/test_numbers.py +++ b/Lib/test/test_ctypes/test_numbers.py @@ -131,11 +131,10 @@ def test_complex(self): self.assertEqual(t(FloatLike()).value, 2+0j) self.assertEqual(t(ComplexLike()).value, 1+1j) - prefix = '>' if sys.byteorder == 'big' else '<' num = t(1.0) - self.assertEqual(memoryview(num).format, prefix + format) + self.assertEqual(memoryview(num).format, format) array = (t * 3)() - self.assertEqual(memoryview(array).format, prefix + format) + self.assertEqual(memoryview(array).format, format) @unittest.skipUnless(hasattr(ctypes, "c_double_complex"), "requires C11 complex type") diff --git a/Lib/test/test_ctypes/test_pep3118.py b/Lib/test/test_ctypes/test_pep3118.py index 11a0744f5a8e36..8e282064ad4281 100644 --- a/Lib/test/test_ctypes/test_pep3118.py +++ b/Lib/test/test_ctypes/test_pep3118.py @@ -1,4 +1,3 @@ -import re import sys import unittest from ctypes import (CFUNCTYPE, POINTER, sizeof, Union, @@ -9,29 +8,12 @@ c_bool, c_float, c_double, c_longdouble, py_object) -if sys.byteorder == "little": - THIS_ENDIAN = "<" - OTHER_ENDIAN = ">" -else: - THIS_ENDIAN = ">" - OTHER_ENDIAN = "<" - - -def normalize(format): - # Remove current endian specifier and white space from a format - # string - if format is None: - return "" - format = format.replace(OTHER_ENDIAN, THIS_ENDIAN) - return re.sub(r"\s", "", format) - - class Test(unittest.TestCase): def test_native_types(self): for tp, fmt, shape, itemtp in native_types: ob = tp() v = memoryview(ob) - self.assertEqual(normalize(v.format), normalize(fmt)) + self.assertEqual(v.format, fmt) if shape: self.assertEqual(len(v), shape[0]) else: @@ -73,6 +55,15 @@ def test_endian_types(self): n = n * dim self.assertEqual(n * v.itemsize, len(v.tobytes())) + def test_memoryview_supports_ctypes_arrays(self): + ArrayType = c_int * 5 + a = ArrayType(123, 42, 1, 2, 3) + m = memoryview(a) + self.assertEqual(m.shape, (5,)) + self.assertEqual(m.format, c_int._type_) + self.assertEqual(list(m), [123, 42, 1, 2, 3]) + self.assertEqual(m[1], 42) + # define some structure classes @@ -124,20 +115,19 @@ class Complete(Structure): ################################################################ # -# This table contains format strings as they look on little endian -# machines. The test replaces '<' with '>' on big endian machines. +# This table contains format strings with native endianness. # # Platform-specific type codes -s_bool = {1: '?', 2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_bool)] -s_short = {2: 'h', 4: 'l', 8: 'q'}[sizeof(c_short)] -s_ushort = {2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_ushort)] -s_int = {2: 'h', 4: 'i', 8: 'q'}[sizeof(c_int)] -s_uint = {2: 'H', 4: 'I', 8: 'Q'}[sizeof(c_uint)] -s_long = {4: 'l', 8: 'q'}[sizeof(c_long)] -s_ulong = {4: 'L', 8: 'Q'}[sizeof(c_ulong)] -s_longlong = "q" -s_ulonglong = "Q" +s_bool = c_bool._type_ +s_short = c_short._type_ +s_ushort = c_ushort._type_ +s_int = c_int._type_ +s_uint = c_uint._type_ +s_long = c_long._type_ +s_ulong = c_ulong._type_ +s_longlong = c_longlong._type_ +s_ulonglong = c_ulonglong._type_ s_float = "f" s_double = "d" s_longdouble = "g" @@ -160,59 +150,59 @@ class Complete(Structure): ## simple types - (c_char, "l:x:>l:y:}".replace('l', s_long), (), BEPoint), - (LEPoint * 1, "T{l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)), - (POINTER(LEPoint), "&T{l:x:>l:y:}".replace('l', s_long2), (), BEPoint), + (LEPoint * 1, "T{l:x:l:y:}", (1,), LEPoint), + (POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long2), (), POINTER(BEPoint)), + (POINTER(LEPoint), "&T{l:x:l:y:}", (), POINTER(LEPoint)), + ] +else: + endian_types = [ + (BEPoint * 1, "T{l:x:l:y:}", (1,), BEPoint), + (LEPoint, "T{` support in the +:mod:`ctypes` module to use the machine’s native format and byte order, +rather than explicitly specify endianness (by ``'<'`` or ``'>'``). The +later kept for byte-swapped types. Patch by Sergey B Kirpichev. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index adfdf44e53604e..0854f38b149d86 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2405,15 +2405,12 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) stginfo->size = fmt->pffi_type->size; stginfo->setfunc = fmt->setfunc; stginfo->getfunc = fmt->getfunc; -#ifdef WORDS_BIGENDIAN - stginfo->format = _ctypes_alloc_format_string_for_type(proto_str, 1); -#else - stginfo->format = _ctypes_alloc_format_string_for_type(proto_str, 0); -#endif + stginfo->format = PyMem_Malloc(1 + strlen(proto_str)); if (stginfo->format == NULL) { Py_DECREF(proto); return -1; } + strcpy(stginfo->format, proto_str); stginfo->paramfunc = PyCSimpleType_paramfunc; /* @@ -2504,14 +2501,14 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) PyObject_SetAttrString(swapped, "__ctype_be__", self); PyObject_SetAttrString(swapped, "__ctype_le__", swapped); /* We are creating the type for the OTHER endian */ - sw_info->format = _ctypes_alloc_format_string("<", stginfo->format+1); + sw_info->format = _ctypes_alloc_format_string_for_type(stginfo->format, 0); #else PyObject_SetAttrString(self, "__ctype_be__", swapped); PyObject_SetAttrString(self, "__ctype_le__", self); PyObject_SetAttrString(swapped, "__ctype_le__", self); PyObject_SetAttrString(swapped, "__ctype_be__", swapped); /* We are creating the type for the OTHER endian */ - sw_info->format = _ctypes_alloc_format_string(">", stginfo->format+1); + sw_info->format = _ctypes_alloc_format_string_for_type(stginfo->format, 1); #endif Py_DECREF(swapped); if (PyErr_Occurred()) {