[pypy-commit] cffi default: Issue #228: "bool" not working in out-of-line FFI objects. Same problem

arigo noreply at buildbot.pypy.org
Mon Nov 2 17:13:24 EST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r2367:bcbbce0b1d78
Date: 2015-11-02 23:12 +0100
http://bitbucket.org/cffi/cffi/changeset/bcbbce0b1d78/

Log:	Issue #228: "bool" not working in out-of-line FFI objects. Same
	problem with all Windows common types. Mostly fixed by moving the
	list of common types to C code. The only remaining corner case I
	can think of is "FILE", which works only if it was mentioned in the
	cdef while building the out-of-line module.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -5861,6 +5861,9 @@
                            (PyObject *)&CTypeDescr_Type);
 }
 
+/* forward, in commontypes.c */
+static PyObject *b__get_common_types(PyObject *self, PyObject *arg);
+
 static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds)
 {
     CDataObject *cd;
@@ -6187,6 +6190,7 @@
     {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS},
 #endif
     {"_get_types", b__get_types, METH_NOARGS},
+    {"_get_common_types", b__get_common_types, METH_O},
     {"_testfunc", b__testfunc, METH_VARARGS},
     {"_testbuff", b__testbuff, METH_VARARGS},
     {"_init_cffi_1_0_external_module", b_init_cffi_1_0_external_module, METH_O},
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -15,6 +15,7 @@
 #include "cglob.c"
 #include "lib_obj.c"
 #include "cdlopen.c"
+#include "commontypes.c"
 
 
 static int init_ffi_lib(PyObject *m)
diff --git a/c/commontypes.c b/c/commontypes.c
new file mode 100644
--- /dev/null
+++ b/c/commontypes.c
@@ -0,0 +1,209 @@
+/* This file must be kept in alphabetical order.  See test_commontypes.py */
+
+#define EQ(key, value)    key "\0" value   /* string concatenation */
+#ifdef _WIN64
+#  define W32_64(X,Y)  Y
+# else
+#  define W32_64(X,Y)  X
+# endif
+
+
+static const char *common_simple_types[] = {
+
+#ifdef MS_WIN32   /* Windows types */
+    EQ("ATOM", "WORD"),
+    EQ("BOOL", "int"),
+    EQ("BOOLEAN", "BYTE"),
+    EQ("BYTE", "unsigned char"),
+    EQ("CCHAR", "char"),
+    EQ("CHAR", "char"),
+    EQ("COLORREF", "DWORD"),
+    EQ("DWORD", "unsigned long"),
+    EQ("DWORD32", "unsigned int"),
+    EQ("DWORD64", "unsigned long long"),
+    EQ("DWORDLONG", "ULONGLONG"),
+    EQ("DWORD_PTR", "ULONG_PTR"),
+    EQ("FLOAT", "float"),
+    EQ("HACCEL", "HANDLE"),
+    EQ("HALF_PTR", W32_64("short","int")),
+    EQ("HBITMAP", "HANDLE"),
+    EQ("HBRUSH", "HANDLE"),
+    EQ("HCOLORSPACE", "HANDLE"),
+    EQ("HCONV", "HANDLE"),
+    EQ("HCONVLIST", "HANDLE"),
+    EQ("HCURSOR", "HICON"),
+    EQ("HDC", "HANDLE"),
+    EQ("HDDEDATA", "HANDLE"),
+    EQ("HDESK", "HANDLE"),
+    EQ("HDROP", "HANDLE"),
+    EQ("HDWP", "HANDLE"),
+    EQ("HENHMETAFILE", "HANDLE"),
+    EQ("HFILE", "int"),
+    EQ("HFONT", "HANDLE"),
+    EQ("HGDIOBJ", "HANDLE"),
+    EQ("HGLOBAL", "HANDLE"),
+    EQ("HHOOK", "HANDLE"),
+    EQ("HICON", "HANDLE"),
+    EQ("HINSTANCE", "HANDLE"),
+    EQ("HKEY", "HANDLE"),
+    EQ("HKL", "HANDLE"),
+    EQ("HLOCAL", "HANDLE"),
+    EQ("HMENU", "HANDLE"),
+    EQ("HMETAFILE", "HANDLE"),
+    EQ("HMODULE", "HINSTANCE"),
+    EQ("HMONITOR", "HANDLE"),
+    EQ("HPALETTE", "HANDLE"),
+    EQ("HPEN", "HANDLE"),
+    EQ("HRESULT", "LONG"),
+    EQ("HRGN", "HANDLE"),
+    EQ("HRSRC", "HANDLE"),
+    EQ("HSZ", "HANDLE"),
+    EQ("HWND", "HANDLE"),
+    EQ("INT", "int"),
+    EQ("INT16", "short"),
+    EQ("INT32", "int"),
+    EQ("INT64", "long long"),
+    EQ("INT8", "signed char"),
+    EQ("INT_PTR", W32_64("int","long long")),
+    EQ("LANGID", "WORD"),
+    EQ("LCID", "DWORD"),
+    EQ("LCTYPE", "DWORD"),
+    EQ("LGRPID", "DWORD"),
+    EQ("LONG", "long"),
+    EQ("LONG32", "int"),
+    EQ("LONG64", "long long"),
+    EQ("LONGLONG", "long long"),
+    EQ("LONG_PTR", W32_64("long","long long")),
+    EQ("LPARAM", "LONG_PTR"),
+    EQ("LPBOOL", "BOOL *"),
+    EQ("LPBYTE", "BYTE *"),
+    EQ("LPCOLORREF", "DWORD *"),
+    EQ("LPCSTR", "const char *"),
+    EQ("LPCVOID", "const void *"),
+    EQ("LPCWSTR", "const WCHAR *"),
+    EQ("LPDWORD", "DWORD *"),
+    EQ("LPHANDLE", "HANDLE *"),
+    EQ("LPINT", "int *"),
+    EQ("LPLONG", "long *"),
+    EQ("LPSTR", "CHAR *"),
+    EQ("LPVOID", "void *"),
+    EQ("LPWORD", "WORD *"),
+    EQ("LPWSTR", "WCHAR *"),
+    EQ("LRESULT", "LONG_PTR"),
+    EQ("PBOOL", "BOOL *"),
+    EQ("PBOOLEAN", "BOOLEAN *"),
+    EQ("PBYTE", "BYTE *"),
+    EQ("PCHAR", "CHAR *"),
+    EQ("PCSTR", "const CHAR *"),
+    EQ("PCWSTR", "const WCHAR *"),
+    EQ("PDWORD", "DWORD *"),
+    EQ("PDWORD32", "DWORD32 *"),
+    EQ("PDWORD64", "DWORD64 *"),
+    EQ("PDWORDLONG", "DWORDLONG *"),
+    EQ("PDWORD_PTR", "DWORD_PTR *"),
+    EQ("PFLOAT", "FLOAT *"),
+    EQ("PHALF_PTR", "HALF_PTR *"),
+    EQ("PHANDLE", "HANDLE *"),
+    EQ("PHKEY", "HKEY *"),
+    EQ("PINT", "int *"),
+    EQ("PINT16", "INT16 *"),
+    EQ("PINT32", "INT32 *"),
+    EQ("PINT64", "INT64 *"),
+    EQ("PINT8", "INT8 *"),
+    EQ("PINT_PTR", "INT_PTR *"),
+    EQ("PLCID", "PDWORD"),
+    EQ("PLONG", "LONG *"),
+    EQ("PLONG32", "LONG32 *"),
+    EQ("PLONG64", "LONG64 *"),
+    EQ("PLONGLONG", "LONGLONG *"),
+    EQ("PLONG_PTR", "LONG_PTR *"),
+    EQ("PSHORT", "SHORT *"),
+    EQ("PSIZE_T", "SIZE_T *"),
+    EQ("PSSIZE_T", "SSIZE_T *"),
+    EQ("PSTR", "CHAR *"),
+    EQ("PUCHAR", "UCHAR *"),
+    EQ("PUHALF_PTR", "UHALF_PTR *"),
+    EQ("PUINT", "UINT *"),
+    EQ("PUINT16", "UINT16 *"),
+    EQ("PUINT32", "UINT32 *"),
+    EQ("PUINT64", "UINT64 *"),
+    EQ("PUINT8", "UINT8 *"),
+    EQ("PUINT_PTR", "UINT_PTR *"),
+    EQ("PULONG", "ULONG *"),
+    EQ("PULONG32", "ULONG32 *"),
+    EQ("PULONG64", "ULONG64 *"),
+    EQ("PULONGLONG", "ULONGLONG *"),
+    EQ("PULONG_PTR", "ULONG_PTR *"),
+    EQ("PUSHORT", "USHORT *"),
+    EQ("PVOID", "void *"),
+    EQ("PWCHAR", "WCHAR *"),
+    EQ("PWORD", "WORD *"),
+    EQ("PWSTR", "WCHAR *"),
+    EQ("QWORD", "unsigned long long"),
+    EQ("SC_HANDLE", "HANDLE"),
+    EQ("SC_LOCK", "LPVOID"),
+    EQ("SERVICE_STATUS_HANDLE", "HANDLE"),
+    EQ("SHORT", "short"),
+    EQ("SIZE_T", "ULONG_PTR"),
+    EQ("SSIZE_T", "LONG_PTR"),
+    EQ("UCHAR", "unsigned char"),
+    EQ("UHALF_PTR", W32_64("unsigned short","unsigned int")),
+    EQ("UINT", "unsigned int"),
+    EQ("UINT16", "unsigned short"),
+    EQ("UINT32", "unsigned int"),
+    EQ("UINT64", "unsigned long long"),
+    EQ("UINT8", "unsigned char"),
+    EQ("UINT_PTR", W32_64("unsigned int","unsigned long long")),
+    EQ("ULONG", "unsigned long"),
+    EQ("ULONG32", "unsigned int"),
+    EQ("ULONG64", "unsigned long long"),
+    EQ("ULONGLONG", "unsigned long long"),
+    EQ("ULONG_PTR", W32_64("unsigned long","unsigned long long")),
+    EQ("USHORT", "unsigned short"),
+    EQ("USN", "LONGLONG"),
+    EQ("VOID", "void"),
+    EQ("WCHAR", "wchar_t"),
+    EQ("WINSTA", "HANDLE"),
+    EQ("WORD", "unsigned short"),
+    EQ("WPARAM", "UINT_PTR"),
+#endif
+
+    EQ("bool", "_Bool"),
+};
+
+
+#undef EQ
+#undef W32_64
+
+#define num_common_simple_types    \
+    (sizeof(common_simple_types) / sizeof(common_simple_types[0]))
+
+
+static const char *get_common_type(const char *search, size_t search_len)
+{
+    const char *entry;
+    int index = search_sorted(common_simple_types, sizeof(const char *),
+                              num_common_simple_types, search, search_len);
+    if (index < 0)
+        return NULL;
+
+    entry = common_simple_types[index];
+    return entry + strlen(entry) + 1;
+}
+
+static PyObject *b__get_common_types(PyObject *self, PyObject *arg)
+{
+    int i, err;
+    for (i = 0; i < num_common_simple_types; i++) {
+        const char *s = common_simple_types[i];
+        PyObject *o = PyString_FromString(s + strlen(s) + 1);
+        if (o == NULL)
+            return NULL;
+        err = PyDict_SetItemString(arg, s, o);
+        Py_DECREF(o);
+        if (err < 0)
+            return NULL;
+    }
+    Py_INCREF(Py_None);
+    return Py_None;
+}
diff --git a/c/parse_c_type.c b/c/parse_c_type.c
--- a/c/parse_c_type.c
+++ b/c/parse_c_type.c
@@ -220,6 +220,8 @@
 #define MAX_SSIZE_T  (((size_t)-1) >> 1)
 
 static int parse_complete(token_t *tok);
+static const char *get_common_type(const char *search, size_t search_len);
+static int parse_common_type_replacement(token_t *tok, const char *replacement);
 
 static int parse_sequel(token_t *tok, int outer)
 {
@@ -442,26 +444,34 @@
     return _CFFI_GETARG(result);
 }
 
+static int search_sorted(const char *const *base,
+                         size_t item_size, int array_len,
+                         const char *search, size_t search_len)
+{
+    int left = 0, right = array_len;
+    const char *baseptr = (const char *)base;
 
-#define MAKE_SEARCH_FUNC(FIELD)                                 \
-  static                                                        \
-  int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \
-                        const char *search, size_t search_len)  \
-  {                                                             \
-      int left = 0, right = ctx->num_##FIELD;                   \
-                                                                \
-      while (left < right) {                                    \
-          int middle = (left + right) / 2;                      \
-          const char *src = ctx->FIELD[middle].name;            \
-          int diff = strncmp(src, search, search_len);          \
-          if (diff == 0 && src[search_len] == '\0')             \
-              return middle;                                    \
-          else if (diff >= 0)                                   \
-              right = middle;                                   \
-          else                                                  \
-              left = middle + 1;                                \
-      }                                                         \
-      return -1;                                                \
+    while (left < right) {
+        int middle = (left + right) / 2;
+        const char *src = *(const char *const *)(baseptr + middle * item_size);
+        int diff = strncmp(src, search, search_len);
+        if (diff == 0 && src[search_len] == '\0')
+            return middle;
+        else if (diff >= 0)
+            right = middle;
+        else
+            left = middle + 1;
+    }
+    return -1;
+}
+
+#define MAKE_SEARCH_FUNC(FIELD)                                         \
+  static                                                                \
+  int search_in_##FIELD(const struct _cffi_type_context_s *ctx,         \
+                        const char *search, size_t search_len)          \
+  {                                                                     \
+      return search_sorted(&ctx->FIELD->name, sizeof(*ctx->FIELD),      \
+                           ctx->num_##FIELD, search, search_len);       \
   }
 
 MAKE_SEARCH_FUNC(globals)
@@ -715,6 +725,7 @@
             break;
         case TOK_IDENTIFIER:
         {
+            const char *replacement;
             int n = search_in_typenames(tok->info->ctx, tok->p, tok->size);
             if (n >= 0) {
                 t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n);
@@ -725,6 +736,14 @@
                 t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n);
                 break;
             }
+            replacement = get_common_type(tok->p, tok->size);
+            if (replacement != NULL) {
+                n = parse_common_type_replacement(tok, replacement);
+                if (n < 0)
+                    return parse_error(tok, "internal error, please report!");
+                t1 = _CFFI_OP(_CFFI_OP_NOOP, n);
+                break;
+            }
             return parse_error(tok, "undefined type name");
         }
         case TOK_STRUCT:
@@ -770,7 +789,8 @@
 
 
 static
-int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
+int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index,
+                      const char *input)
 {
     int result;
     token_t token;
@@ -781,12 +801,26 @@
     token.p = input;
     token.size = 0;
     token.output = info->output;
-    token.output_index = 0;
+    token.output_index = *output_index;
 
     next_token(&token);
     result = parse_complete(&token);
 
+    *output_index = token.output_index;
     if (token.kind != TOK_END)
         return parse_error(&token, "unexpected symbol");
     return result;
 }
+
+static
+int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
+{
+    size_t output_index = 0;
+    return parse_c_type_from(info, &output_index, input);
+}
+
+static
+int parse_common_type_replacement(token_t *tok, const char *replacement)
+{
+    return parse_c_type_from(tok->info, &tok->output_index, replacement);
+}
diff --git a/cffi/commontypes.py b/cffi/commontypes.py
--- a/cffi/commontypes.py
+++ b/cffi/commontypes.py
@@ -7,6 +7,13 @@
     'bool': '_Bool',
     }
 
+try:
+    # fetch "bool" and all simple Windows types
+    from _cffi_backend import _get_common_types
+    _get_common_types(COMMON_TYPES)
+except ImportError:
+    pass
+
 for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
     if _type.endswith('_t'):
         COMMON_TYPES[_type] = _type
@@ -14,212 +21,35 @@
 
 _CACHE = {}
 
-def resolve_common_type(commontype):
+def resolve_common_type(parser, commontype):
     try:
         return _CACHE[commontype]
     except KeyError:
-        result = COMMON_TYPES.get(commontype, commontype)
-        if not isinstance(result, str):
-            pass    # result is already a BaseType
-        elif result.endswith(' *'):
-            if result.startswith('const '):
-                result = model.ConstPointerType(
-                    resolve_common_type(result[6:-2]))
-            else:
-                result = model.PointerType(resolve_common_type(result[:-2]))
-        elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
-            result = model.PrimitiveType(result)
-        elif result == 'set-unicode-needed':
+        cdecl = COMMON_TYPES.get(commontype, commontype)
+        if not isinstance(cdecl, str):
+            result, quals = cdecl, 0    # cdecl is already a BaseType
+        elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
+            result, quals = model.PrimitiveType(cdecl), 0
+        elif cdecl == 'set-unicode-needed':
             raise api.FFIError("The Windows type %r is only available after "
                                "you call ffi.set_unicode()" % (commontype,))
         else:
-            if commontype == result:
+            if commontype == cdecl:
                 raise api.FFIError("Unsupported type: %r.  Please file a bug "
                                    "if you think it should be." % (commontype,))
-            result = resolve_common_type(result)   # recursively
+            result, quals = parser.parse_type_and_quals(cdecl)   # recursive
+
         assert isinstance(result, model.BaseTypeByIdentity)
-        _CACHE[commontype] = result
-        return result
+        _CACHE[commontype] = result, quals
+        return result, quals
 
 
 # ____________________________________________________________
-# Windows common types
+# extra types for Windows (most of them are in commontypes.c)
 
 
-def win_common_types(maxsize):
-    result = {}
-    if maxsize < (1<<32):
-        result.update({      # Windows 32-bits
-            'HALF_PTR': 'short',
-            'INT_PTR': 'int',
-            'LONG_PTR': 'long',
-            'UHALF_PTR': 'unsigned short',
-            'UINT_PTR': 'unsigned int',
-            'ULONG_PTR': 'unsigned long',
-            })
-    else:
-        result.update({      # Windows 64-bits
-            'HALF_PTR': 'int',
-            'INT_PTR': 'long long',
-            'LONG_PTR': 'long long',
-            'UHALF_PTR': 'unsigned int',
-            'UINT_PTR': 'unsigned long long',
-            'ULONG_PTR': 'unsigned long long',
-            })
-    result.update({
-        "BYTE": "unsigned char",
-        "BOOL": "int",
-        "CCHAR": "char",
-        "CHAR": "char",
-        "DWORD": "unsigned long",
-        "DWORD32": "unsigned int",
-        "DWORD64": "unsigned long long",
-        "FLOAT": "float",
-        "INT": "int",
-        "INT8": "signed char",
-        "INT16": "short",
-        "INT32": "int",
-        "INT64": "long long",
-        "LONG": "long",
-        "LONGLONG": "long long",
-        "LONG32": "int",
-        "LONG64": "long long",
-        "WORD": "unsigned short",
-        "PVOID": model.voidp_type,
-        "ULONGLONG": "unsigned long long",
-        "WCHAR": "wchar_t",
-        "SHORT": "short",
-        "UCHAR": "unsigned char",
-        "UINT": "unsigned int",
-        "UINT8": "unsigned char",
-        "UINT16": "unsigned short",
-        "UINT32": "unsigned int",
-        "UINT64": "unsigned long long",
-        "ULONG": "unsigned long",
-        "ULONG32": "unsigned int",
-        "ULONG64": "unsigned long long",
-        "USHORT": "unsigned short",
-
-        "SIZE_T": "ULONG_PTR",
-        "SSIZE_T": "LONG_PTR",
-        "ATOM": "WORD",
-        "BOOLEAN": "BYTE",
-        "COLORREF": "DWORD",
-
-        "HANDLE": "PVOID",
-        "DWORDLONG": "ULONGLONG",
-        "DWORD_PTR": "ULONG_PTR",
-        "HACCEL": "HANDLE",
-
-        "HBITMAP": "HANDLE",
-        "HBRUSH": "HANDLE",
-        "HCOLORSPACE": "HANDLE",
-        "HCONV": "HANDLE",
-        "HCONVLIST": "HANDLE",
-        "HDC": "HANDLE",
-        "HDDEDATA": "HANDLE",
-        "HDESK": "HANDLE",
-        "HDROP": "HANDLE",
-        "HDWP": "HANDLE",
-        "HENHMETAFILE": "HANDLE",
-        "HFILE": "int",
-        "HFONT": "HANDLE",
-        "HGDIOBJ": "HANDLE",
-        "HGLOBAL": "HANDLE",
-        "HHOOK": "HANDLE",
-        "HICON": "HANDLE",
-        "HCURSOR": "HICON",
-        "HINSTANCE": "HANDLE",
-        "HKEY": "HANDLE",
-        "HKL": "HANDLE",
-        "HLOCAL": "HANDLE",
-        "HMENU": "HANDLE",
-        "HMETAFILE": "HANDLE",
-        "HMODULE": "HINSTANCE",
-        "HMONITOR": "HANDLE",
-        "HPALETTE": "HANDLE",
-        "HPEN": "HANDLE",
-        "HRESULT": "LONG",
-        "HRGN": "HANDLE",
-        "HRSRC": "HANDLE",
-        "HSZ": "HANDLE",
-        "WINSTA": "HANDLE",
-        "HWND": "HANDLE",
-
-        "LANGID": "WORD",
-        "LCID": "DWORD",
-        "LCTYPE": "DWORD",
-        "LGRPID": "DWORD",
-        "LPARAM": "LONG_PTR",
-        "LPBOOL": "BOOL *",
-        "LPBYTE": "BYTE *",
-        "LPCOLORREF": "DWORD *",
-        "LPCSTR": "const char *",
-
-        "LPCVOID": model.const_voidp_type,
-        "LPCWSTR": "const WCHAR *",
-        "LPDWORD": "DWORD *",
-        "LPHANDLE": "HANDLE *",
-        "LPINT": "int *",
-        "LPLONG": "long *",
-        "LPSTR": "CHAR *",
-        "LPWSTR": "WCHAR *",
-        "LPVOID": model.voidp_type,
-        "LPWORD": "WORD *",
-        "LRESULT": "LONG_PTR",
-        "PBOOL": "BOOL *",
-        "PBOOLEAN": "BOOLEAN *",
-        "PBYTE": "BYTE *",
-        "PCHAR": "CHAR *",
-        "PCSTR": "const CHAR *",
-        "PCWSTR": "const WCHAR *",
-        "PDWORD": "DWORD *",
-        "PDWORDLONG": "DWORDLONG *",
-        "PDWORD_PTR": "DWORD_PTR *",
-        "PDWORD32": "DWORD32 *",
-        "PDWORD64": "DWORD64 *",
-        "PFLOAT": "FLOAT *",
-        "PHALF_PTR": "HALF_PTR *",
-        "PHANDLE": "HANDLE *",
-        "PHKEY": "HKEY *",
-        "PINT": "int *",
-        "PINT_PTR": "INT_PTR *",
-        "PINT8": "INT8 *",
-        "PINT16": "INT16 *",
-        "PINT32": "INT32 *",
-        "PINT64": "INT64 *",
-        "PLCID": "PDWORD",
-        "PLONG": "LONG *",
-        "PLONGLONG": "LONGLONG *",
-        "PLONG_PTR": "LONG_PTR *",
-        "PLONG32": "LONG32 *",
-        "PLONG64": "LONG64 *",
-        "PSHORT": "SHORT *",
-        "PSIZE_T": "SIZE_T *",
-        "PSSIZE_T": "SSIZE_T *",
-        "PSTR": "CHAR *",
-        "PUCHAR": "UCHAR *",
-        "PUHALF_PTR": "UHALF_PTR *",
-        "PUINT": "UINT *",
-        "PUINT_PTR": "UINT_PTR *",
-        "PUINT8": "UINT8 *",
-        "PUINT16": "UINT16 *",
-        "PUINT32": "UINT32 *",
-        "PUINT64": "UINT64 *",
-        "PULONG": "ULONG *",
-        "PULONGLONG": "ULONGLONG *",
-        "PULONG_PTR": "ULONG_PTR *",
-        "PULONG32": "ULONG32 *",
-        "PULONG64": "ULONG64 *",
-        "PUSHORT": "USHORT *",
-        "PWCHAR": "WCHAR *",
-        "PWORD": "WORD *",
-        "PWSTR": "WCHAR *",
-        "QWORD": "unsigned long long",
-        "SC_HANDLE": "HANDLE",
-        "SC_LOCK": "LPVOID",
-        "SERVICE_STATUS_HANDLE": "HANDLE",
-
+def win_common_types():
+    return {
         "UNICODE_STRING": model.StructType(
             "_UNICODE_STRING",
             ["Length",
@@ -232,10 +62,6 @@
         "PUNICODE_STRING": "UNICODE_STRING *",
         "PCUNICODE_STRING": "const UNICODE_STRING *",
 
-        "USN": "LONGLONG",
-        "VOID": model.void_type,
-        "WPARAM": "UINT_PTR",
-
         "TBYTE": "set-unicode-needed",
         "TCHAR": "set-unicode-needed",
         "LPCTSTR": "set-unicode-needed",
@@ -244,9 +70,7 @@
         "PTSTR": "set-unicode-needed",
         "PTBYTE": "set-unicode-needed",
         "PTCHAR": "set-unicode-needed",
-        })
-    return result
-
+        }
 
 if sys.platform == 'win32':
-    COMMON_TYPES.update(win_common_types(sys.maxsize))
+    COMMON_TYPES.update(win_common_types())
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -472,7 +472,8 @@
                 if ident == '__dotdotdot__':
                     raise api.FFIError(':%d: bad usage of "..."' %
                             typenode.coord.line)
-                return resolve_common_type(ident), quals
+                tp0, quals0 = resolve_common_type(self, ident)
+                return tp0, (quals | quals0)
             #
             if isinstance(type, pycparser.c_ast.Struct):
                 # 'struct foobar'
diff --git a/testing/cffi0/test_parsing.py b/testing/cffi0/test_parsing.py
--- a/testing/cffi0/test_parsing.py
+++ b/testing/cffi0/test_parsing.py
@@ -286,38 +286,16 @@
              "typedef int (*func_t)(void_t);")
     assert ffi.typeof("func_t").args == ()
 
-def test_win_common_types():
-    from cffi.commontypes import COMMON_TYPES, _CACHE
-    from cffi.commontypes import win_common_types, resolve_common_type
-    #
-    def clear_all(extra={}, old_dict=COMMON_TYPES.copy()):
-        COMMON_TYPES.clear()
-        COMMON_TYPES.update(old_dict)
-        COMMON_TYPES.update(extra)
-        _CACHE.clear()
-    #
-    for maxsize in [2**32-1, 2**64-1]:
-        ct = win_common_types(maxsize)
-        clear_all(ct)
-        for key in sorted(ct):
-            if ct[key] != 'set-unicode-needed':
-                resolve_common_type(key)
-    # assert did not crash
-    # now try to use e.g. WPARAM (-> UINT_PTR -> unsigned 32/64-bit)
-    for maxsize in [2**32-1, 2**64-1]:
-        ct = win_common_types(maxsize)
-        clear_all(ct)
-        ffi = FFI()
-        value = int(ffi.cast("WPARAM", -1))
-        assert value == maxsize
-    #
-    clear_all()
-
 def test_WPARAM_on_windows():
     if sys.platform != 'win32':
         py.test.skip("Only for Windows")
     ffi = FFI()
     ffi.cdef("void f(WPARAM);")
+    #
+    # WPARAM -> UINT_PTR -> unsigned 32/64-bit integer
+    ffi = FFI()
+    value = int(ffi.cast("WPARAM", -42))
+    assert value == sys.maxsize * 2 - 40
 
 def test__is_constant_globalvar():
     for input, expected_output in [
diff --git a/testing/cffi1/test_commontypes.py b/testing/cffi1/test_commontypes.py
new file mode 100644
--- /dev/null
+++ b/testing/cffi1/test_commontypes.py
@@ -0,0 +1,15 @@
+import py, os, cffi
+import _cffi_backend
+
+
+def test_alphabetical_order():
+    f = open(os.path.join(os.path.dirname(cffi.__file__),
+                          '..', 'c', 'commontypes.c'))
+    lines = [line for line in f.readlines() if line.strip().startswith('EQ(')]
+    f.close()
+    assert lines == sorted(lines)
+
+def test_get_common_types():
+    d = {}
+    _cffi_backend._get_common_types(d)
+    assert d["bool"] == "_Bool"
diff --git a/testing/cffi1/test_ffi_obj.py b/testing/cffi1/test_ffi_obj.py
--- a/testing/cffi1/test_ffi_obj.py
+++ b/testing/cffi1/test_ffi_obj.py
@@ -395,3 +395,17 @@
         return ffi.NULL
     alloc5 = ffi.new_allocator(myalloc5)
     py.test.raises(MemoryError, alloc5, "int[5]")
+
+def test_bool_issue228():
+    ffi = _cffi1_backend.FFI()
+    fntype = ffi.typeof("int(*callback)(bool is_valid)")
+    assert repr(fntype.args[0]) == "<ctype '_Bool'>"
+
+def test_cast_from_int_type_to_bool():
+    ffi = _cffi1_backend.FFI()
+    for basetype in ['char', 'short', 'int', 'long', 'long long']:
+        for sign in ['signed', 'unsigned']:
+            type = '%s %s' % (sign, basetype)
+            assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
+            assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
+            assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
diff --git a/testing/cffi1/test_parse_c_type.py b/testing/cffi1/test_parse_c_type.py
--- a/testing/cffi1/test_parse_c_type.py
+++ b/testing/cffi1/test_parse_c_type.py
@@ -19,8 +19,11 @@
 ffi.cdef(header)
 
 lib = ffi.verify(
-        open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read(),
-        include_dirs=[cffi_dir])
+        open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read() + """
+static const char *get_common_type(const char *search, size_t search_len) {
+    return NULL;
+}
+""",    include_dirs=[cffi_dir])
 
 class ParseError(Exception):
     pass
diff --git a/testing/cffi1/test_verify1.py b/testing/cffi1/test_verify1.py
--- a/testing/cffi1/test_verify1.py
+++ b/testing/cffi1/test_verify1.py
@@ -1494,15 +1494,6 @@
             assert lib.foo(0) == 1
             py.test.raises(TypeError, lib.foo, 0.0)
 
-def test_cast_from_int_type_to_bool():
-    ffi = FFI()
-    for basetype in ['char', 'short', 'int', 'long', 'long long']:
-        for sign in ['signed', 'unsigned']:
-            type = '%s %s' % (sign, basetype)
-            assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
-            assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
-            assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
-
 def test_addressof():
     ffi = FFI()
     ffi.cdef("""


More information about the pypy-commit mailing list