From a8c7223f097167f67b6a6f62064d59371434727b Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 28 Aug 2017 14:08:49 +0200 Subject: [PATCH 1/2] [2.7] bpo-10746: Fix ctypes PEP 3118 type codes for c_long, c_bool, c_int (GH-31) Ctypes currently produces wrong pep3118 type codes for several types. E.g. memoryview(ctypes.c_long()).format gives "' endian specification in the struct syntax also turns on the "standard size" mode, which makes type characters have a platform-independent meaning, which does not match with the codes used internally in ctypes. The struct module format syntax also does not allow specifying native-size non-native-endian items. This commit adds a converter function that maps the internal ctypes codes to appropriate struct module standard-size codes in the pep3118 format strings. The tests are modified to check for this.. (cherry picked from commit 07f1658aa09f6798793c473c72b2951b7fefe220) --- Lib/ctypes/test/test_pep3118.py | 83 ++++++++++++------- .../2017-08-28-13-01-05.bpo-10746.nmAvfu.rst | 1 + Modules/_ctypes/_ctypes.c | 69 ++++++++++++++- 3 files changed, 123 insertions(+), 30 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-08-28-13-01-05.bpo-10746.nmAvfu.rst diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index 3e007e1b41d5b6..49a1356a2c4424 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -109,6 +109,34 @@ class Complete(Structure): # This table contains format strings as they look on little endian # machines. The test replaces '<' with '>' on big endian machines. # + +# 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_float = "f" +s_double = "d" +s_longdouble = "g" + +# Alias definitions in ctypes/__init__.py +if c_int is c_long: + s_int = s_long +if c_uint is c_ulong: + s_uint = s_ulong +if c_longlong is c_long: + s_longlong = s_long +if c_ulonglong is c_ulong: + s_ulonglong = s_ulong +if c_longdouble is c_double: + s_longdouble = s_double + + native_types = [ # type format shape calc itemsize @@ -117,52 +145,51 @@ class Complete(Structure): (c_char, "l:x:>l:y:}", None, BEPoint), - (LEPoint, "T{l:x:>l:y:}", None, POINTER(BEPoint)), - (POINTER(LEPoint), "&T{l:x:>l:y:}".replace('l', s_long), None, BEPoint), + (LEPoint, "T{l:x:>l:y:}".replace('l', s_long), None, POINTER(BEPoint)), + (POINTER(LEPoint), "&T{' : '<'; + result[1] = pep_code; + result[2] = '\0'; + return result; +} + /* Allocate a memory block for a pep3118 format string, copy prefix (if non-null) and suffix into it. Returns NULL on failure, with the error @@ -1999,9 +2064,9 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->setfunc = fmt->setfunc; stgdict->getfunc = fmt->getfunc; #ifdef WORDS_BIGENDIAN - stgdict->format = _ctypes_alloc_format_string(">", proto_str); + stgdict->format = _ctypes_alloc_format_string_for_type(proto_str[0], 1); #else - stgdict->format = _ctypes_alloc_format_string("<", proto_str); + stgdict->format = _ctypes_alloc_format_string_for_type(proto_str[0], 0); #endif if (stgdict->format == NULL) { Py_DECREF(result); From 33b7e42c1c5ed031cc11b8e2e1f5095cd5daf3e5 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 2 Sep 2017 16:31:11 +0300 Subject: [PATCH 2/2] [2.7] bpo-10746: ensure SIZEOF__BOOL is defined --- Modules/_ctypes/_ctypes.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 1babbc7ad5dab3..025d3026d877cc 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,6 +128,12 @@ bytes(cdata) #endif #include "ctypes.h" +/* Definition matching cfield.c:724 */ +#ifndef HAVE_C99_BOOL +#undef SIZEOF__BOOL +#define SIZEOF__BOOL 1 +#endif + PyObject *PyExc_ArgError; /* This dict maps ctypes types to POINTER types */