From: Pauli Virtanen Date: Mon, 28 Aug 2017 12:08:49 +0000 (+0200) Subject: bpo-10746: Fix ctypes PEP 3118 type codes for c_long, c_bool, c_int (#31) X-Git-Tag: v3.7.0a1~211 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=07f1658aa09f6798793c473c72b2951b7fefe220;p=python bpo-10746: Fix ctypes PEP 3118 type codes for c_long, c_bool, c_int (#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. --- diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index d68397ea80..f3c0e23e53 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -112,6 +112,34 @@ Complete._fields_ = [("a", c_long)] # 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 @@ -120,52 +148,51 @@ native_types = [ (c_char, "l:x:>l:y:}", (), BEPoint), - (LEPoint, "T{l:x:>l:y:}", (), POINTER(BEPoint)), - (POINTER(LEPoint), "&T{l:x:>l:y:}".replace('l', s_long), (), BEPoint), + (LEPoint, "T{l:x:>l:y:}".replace('l', s_long), (), 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 @@ -1930,9 +1995,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);