Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r2368:8b042b8ebb63 Date: 2015-11-03 08:47 +0100 http://bitbucket.org/cffi/cffi/changeset/8b042b8ebb63/
Log: Issue #228: do the same for "FILE". Only remaining case now is the very obscure Windows type UNICODE_STRING. I think it is unlikely that someone hits the case of their cdef not mentioning UNICODE_STRING but their runtime code still wants to use it, so I'll close this issue. diff --git a/c/commontypes.c b/c/commontypes.c --- a/c/commontypes.c +++ b/c/commontypes.c @@ -23,6 +23,11 @@ EQ("DWORD64", "unsigned long long"), EQ("DWORDLONG", "ULONGLONG"), EQ("DWORD_PTR", "ULONG_PTR"), +#endif + + EQ("FILE", "struct _IO_FILE"), + +#ifdef MS_WIN32 /* more Windows types */ EQ("FLOAT", "float"), EQ("HACCEL", "HANDLE"), EQ("HALF_PTR", W32_64("short","int")), 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 @@ -755,10 +755,15 @@ return parse_error(tok, "struct or union name expected"); n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size); - if (n < 0) - return parse_error(tok, "undefined struct/union name"); - if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) != 0) - ^ (kind == TOK_UNION)) + if (n < 0) { + if (kind == TOK_STRUCT && tok->size == 8 && + !memcmp(tok->p, "_IO_FILE", 8)) + n = _CFFI__IO_FILE_STRUCT; + else + return parse_error(tok, "undefined struct/union name"); + } + else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) + != 0) ^ (kind == TOK_UNION)) return parse_error(tok, "wrong kind of tag: struct vs union"); t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n); diff --git a/c/realize_c_type.c b/c/realize_c_type.c --- a/c/realize_c_type.c +++ b/c/realize_c_type.c @@ -314,6 +314,16 @@ _cffi_opcode_t op2; const struct _cffi_struct_union_s *s; + if (sindex == _CFFI__IO_FILE_STRUCT) { + /* returns a single global cached opaque type */ + static PyObject *file_struct = NULL; + if (file_struct == NULL) + file_struct = new_struct_or_union_type("struct _IO_FILE", + CT_STRUCT | CT_IS_FILE); + Py_XINCREF(file_struct); + return file_struct; + } + s = &builder->ctx.struct_unions[sindex]; op2 = builder->ctx.types[s->type_index]; if ((((uintptr_t)op2) & 1) == 0) { @@ -330,9 +340,9 @@ (s->flags & _CFFI_F_UNION) ? "union " : "struct ", s->name); if (strcmp(name, "struct _IO_FILE") == 0) - flags |= CT_IS_FILE; - - x = new_struct_or_union_type(name, flags); + x = _realize_c_struct_or_union(builder, _CFFI__IO_FILE_STRUCT); + else + x = new_struct_or_union_type(name, flags); if (x == NULL) return NULL; diff --git a/cffi/cffi_opcode.py b/cffi/cffi_opcode.py --- a/cffi/cffi_opcode.py +++ b/cffi/cffi_opcode.py @@ -110,6 +110,8 @@ _UNKNOWN_FLOAT_PRIM = -2 _UNKNOWN_LONG_DOUBLE = -3 +_IO_FILE_STRUCT = -1 + PRIMITIVE_TO_INDEX = { 'char': PRIM_CHAR, 'short': PRIM_SHORT, diff --git a/cffi/commontypes.py b/cffi/commontypes.py --- a/cffi/commontypes.py +++ b/cffi/commontypes.py @@ -2,10 +2,7 @@ from . import api, model -COMMON_TYPES = { - 'FILE': model.unknown_type('FILE', '_IO_FILE'), - 'bool': '_Bool', - } +COMMON_TYPES = {} try: # fetch "bool" and all simple Windows types @@ -14,6 +11,9 @@ except ImportError: pass +COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') +COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above + for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: if _type.endswith('_t'): COMMON_TYPES[_type] = _type diff --git a/cffi/parse_c_type.h b/cffi/parse_c_type.h --- a/cffi/parse_c_type.h +++ b/cffi/parse_c_type.h @@ -83,6 +83,8 @@ #define _CFFI__UNKNOWN_FLOAT_PRIM (-2) #define _CFFI__UNKNOWN_LONG_DOUBLE (-3) +#define _CFFI__IO_FILE_STRUCT (-1) + struct _cffi_global_s { const char *name; 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 @@ -401,6 +401,12 @@ fntype = ffi.typeof("int(*callback)(bool is_valid)") assert repr(fntype.args[0]) == "<ctype '_Bool'>" +def test_FILE_issue228(): + fntype1 = _cffi1_backend.FFI().typeof("FILE *") + fntype2 = _cffi1_backend.FFI().typeof("FILE *") + assert repr(fntype1) == "<ctype 'struct _IO_FILE *'>" + assert fntype1 is fntype2 + def test_cast_from_int_type_to_bool(): ffi = _cffi1_backend.FFI() for basetype in ['char', 'short', 'int', 'long', 'long long']: 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 @@ -2246,3 +2246,26 @@ ffi = FFI() ffi.cdef("struct s { char *const *a; };") ffi.verify("struct s { char *const *a; };") + +def test_share_FILE(): + ffi1 = FFI() + ffi1.cdef("void do_stuff(FILE *);") + lib1 = ffi1.verify("void do_stuff(FILE *f) { (void)f; }") + ffi2 = FFI() + ffi2.cdef("FILE *barize(void);") + lib2 = ffi2.verify("FILE *barize(void) { return NULL; }") + lib1.do_stuff(lib2.barize()) + +def test_win_common_types(): + if sys.platform != 'win32': + py.test.skip("Windows only") + ffi = FFI() + ffi.set_unicode(True) + ffi.verify("") + assert ffi.typeof("PBYTE") is ffi.typeof("unsigned char *") + if sys.maxsize > 2**32: + expected = "unsigned long long" + else: + expected = "unsigned int" + assert ffi.typeof("UINT_PTR") is ffi.typeof(expected) + assert ffi.typeof("PTSTR") is ffi.typeof("wchar_t *") _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit