[pypy-commit] cffi default: Issue #228: do the same for "FILE". Only remaining case now is the
arigo
noreply at buildbot.pypy.org
Tue Nov 3 02:47:14 EST 2015
Author: Armin Rigo <arigo at 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 *")
More information about the pypy-commit
mailing list