summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/_cffi_backend.c4
-rw-r--r--c/cffi1_module.c1
-rw-r--r--c/commontypes.c209
-rw-r--r--c/parse_c_type.c76
-rw-r--r--cffi/commontypes.py224
-rw-r--r--cffi/cparser.py3
-rw-r--r--testing/cffi0/test_parsing.py32
-rw-r--r--testing/cffi1/test_commontypes.py15
-rw-r--r--testing/cffi1/test_ffi_obj.py14
-rw-r--r--testing/cffi1/test_parse_c_type.py7
-rw-r--r--testing/cffi1/test_verify1.py9
11 files changed, 334 insertions, 260 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index 1a2e2b8..0a374b1 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -5861,6 +5861,9 @@ static PyObject *b__get_types(PyObject *self, PyObject *noarg)
(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 @@ static PyMethodDef FFIBackendMethods[] = {
{"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
index 6cdc2ff..b8668b7 100644
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -15,6 +15,7 @@ static PyTypeObject Lib_Type; /* forward */
#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
index 0000000..86a3e08
--- /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
index 80cd3ff..58c85a8 100644
--- a/c/parse_c_type.c
+++ b/c/parse_c_type.c
@@ -220,6 +220,8 @@ static int write_ds(token_t *tok, _cffi_opcode_t ds)
#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 @@ static int parse_sequel(token_t *tok, int outer)
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;
+
+ 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) \
- { \
- 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; \
+#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 @@ static int parse_complete(token_t *tok)
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 @@ static int parse_complete(token_t *tok)
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_complete(token_t *tok)
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 @@ int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
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
index 04a5868..60f2532 100644
--- a/cffi/commontypes.py
+++ b/cffi/commontypes.py
@@ -7,6 +7,13 @@ COMMON_TYPES = {
'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 @@ del _type
_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
-
-
-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",
+# extra types for Windows (most of them are in commontypes.c)
- "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 @@ def win_common_types(maxsize):
"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 @@ def win_common_types(maxsize):
"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
index cd5bea6..9be70c6 100644
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -472,7 +472,8 @@ class Parser(object):
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
index 4b10cc4..dea6126 100644
--- a/testing/cffi0/test_parsing.py
+++ b/testing/cffi0/test_parsing.py
@@ -286,38 +286,16 @@ def test_void_renamed_as_only_arg():
"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
index 0000000..212da8d
--- /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
index 8241c75..253206a 100644
--- a/testing/cffi1/test_ffi_obj.py
+++ b/testing/cffi1/test_ffi_obj.py
@@ -395,3 +395,17 @@ def test_ffi_new_allocator_4():
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
index 479e0e8..e90243d 100644
--- a/testing/cffi1/test_parse_c_type.py
+++ b/testing/cffi1/test_parse_c_type.py
@@ -19,8 +19,11 @@ ffi = cffi.FFI()
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
index ffc2fc3..4678736 100644
--- a/testing/cffi1/test_verify1.py
+++ b/testing/cffi1/test_verify1.py
@@ -1494,15 +1494,6 @@ def test_cannot_pass_float():
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("""