summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cffi/api.py53
-rw-r--r--cffi/model.py2
-rw-r--r--new/ffi_obj.c54
-rw-r--r--new/parse_c_type.c4
-rw-r--r--new/recompiler.py35
-rw-r--r--new/test_dlopen.py28
6 files changed, 120 insertions, 56 deletions
diff --git a/cffi/api.py b/cffi/api.py
index f74a92c..efd42bb 100644
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -568,23 +568,48 @@ def _builtin_function_type(func):
return ffi._get_cached_btype(tp)
def _set_cdef_types(ffi):
+ from . import model
+
+ all_structs = {}
+ all_typedefs = {}
+ for name, tp in ffi._parser._declarations.items():
+ kind, basename = name.split(' ', 1)
+ if kind == 'struct' or kind == 'union' or kind == 'anonymous':
+ all_structs[tp.name] = tp
+ elif kind == 'typedef':
+ all_typedefs[basename] = tp
+ if getattr(tp, "origin", None) == "unknown_type":
+ all_structs[tp.name] = tp
+ elif isinstance(tp, model.NamedPointerType):
+ all_structs[tp.totype.name] = tp.totype
+
struct_unions = []
pending_completion = []
- lst = ffi._parser._declarations.items()
- lst = sorted(lst, key=lambda x: x[0].split(' ', 1)[1])
- for name, tp in lst:
- kind, basename = name.split(' ', 1)
- if kind == 'struct' or kind == 'union':
- if kind == 'struct':
- BType = _cffi1_backend.new_struct_type(basename)
- else:
- BType = _cffi1_backend.new_union_type(basename)
- struct_unions.append(basename)
- struct_unions.append(BType)
- if not tp.partial and tp.fldtypes is not None:
- pending_completion.append((tp, BType))
+ for name, tp in sorted(all_structs.items()):
+ if not isinstance(tp, model.UnionType):
+ BType = _cffi1_backend.new_struct_type(name)
+ else:
+ BType = _cffi1_backend.new_union_type(name)
+ struct_unions.append(name)
+ struct_unions.append(BType)
+ if not tp.partial and tp.fldtypes is not None:
+ pending_completion.append((tp, BType))
+ #
+ typenames = []
+ for name, tp in sorted(all_typedefs.items()):
+ cname = tp._get_c_name()
+ if cname == name:
+ assert isinstance(tp, model.StructOrUnionOrEnum)
+ cname = '%s %s' % (tp.kind, tp.name)
+ try:
+ BType = ffi.typeof(cname)
+ except ffi.error:
+ ffi.__set_types(struct_unions, typenames)
+ BType = ffi.typeof(cname)
+ typenames.append(name)
+ typenames.append(BType)
#
- ffi.__set_types(struct_unions)
+ ffi.__set_types(struct_unions, typenames)
#
for tp, BType in pending_completion:
fldtypes = [ffi.typeof(ftp._get_c_name()) for ftp in tp.fldtypes]
diff --git a/cffi/model.py b/cffi/model.py
index 7152f24..955a045 100644
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -459,7 +459,7 @@ def unknown_type(name, structname=None):
def unknown_ptr_type(name, structname=None):
if structname is None:
- structname = '*$%s' % name
+ structname = '$$%s' % name
tp = StructType(structname, None, None, None)
return NamedPointerType(tp, name)
diff --git a/new/ffi_obj.c b/new/ffi_obj.c
index babcfb2..37f20eb 100644
--- a/new/ffi_obj.c
+++ b/new/ffi_obj.c
@@ -525,15 +525,18 @@ static int ffi_set_errno(PyObject *self, PyObject *newval, void *closure)
static PyObject *ffi__set_types(FFIObject *self, PyObject *args)
{
- PyObject *lst1;
+ PyObject *lst1, *lst2;
_cffi_opcode_t *types = NULL;
struct _cffi_struct_union_s *struct_unions = NULL;
+ struct _cffi_typename_s *typenames = NULL;
- if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &lst1))
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &PyList_Type, &lst1, &PyList_Type, &lst2))
return NULL;
if (self->ctx_is_static) {
bad_usage:
+ PyMem_Free(typenames);
PyMem_Free(struct_unions);
PyMem_Free(types);
if (!PyErr_Occurred())
@@ -543,19 +546,24 @@ static PyObject *ffi__set_types(FFIObject *self, PyObject *args)
cleanup_builder_c(self->types_builder);
- int i, lst_length = PyList_GET_SIZE(lst1) / 2;
- Py_ssize_t new_size_1 = sizeof(_cffi_opcode_t) * lst_length;
- Py_ssize_t new_size_2 = sizeof(struct _cffi_struct_union_s) * lst_length;
- types = PyMem_Malloc(new_size_1);
- struct_unions = PyMem_Malloc(new_size_2);
- if (!types || !struct_unions) {
+ int i;
+ int lst1_length = PyList_GET_SIZE(lst1) / 2;
+ int lst2_length = PyList_GET_SIZE(lst2) / 2;
+ Py_ssize_t newsize0 = sizeof(_cffi_opcode_t) * (lst1_length + lst2_length);
+ Py_ssize_t newsize1 = sizeof(struct _cffi_struct_union_s) * lst1_length;
+ Py_ssize_t newsize2 = sizeof(struct _cffi_typename_s) * lst2_length;
+ types = PyMem_Malloc(newsize0);
+ struct_unions = PyMem_Malloc(newsize1);
+ typenames = PyMem_Malloc(newsize2);
+ if (!types || !struct_unions || !typenames) {
PyErr_NoMemory();
goto bad_usage;
}
- memset(types, 0, new_size_1);
- memset(struct_unions, 0, new_size_2);
+ memset(types, 0, newsize0);
+ memset(struct_unions, 0, newsize1);
+ memset(typenames, 0, newsize2);
- for (i = 0; i < lst_length; i++) {
+ for (i = 0; i < lst1_length; i++) {
PyObject *x = PyList_GET_ITEM(lst1, i * 2);
if (!PyString_Check(x))
goto bad_usage;
@@ -570,18 +578,32 @@ static PyObject *ffi__set_types(FFIObject *self, PyObject *args)
struct_unions[i].size = (size_t)-2;
struct_unions[i].alignment = -2;
}
- for (i = 0; i < lst_length; i++) {
+ for (i = 0; i < lst2_length; i++) {
+ PyObject *x = PyList_GET_ITEM(lst2, i * 2);
+ if (!PyString_Check(x))
+ goto bad_usage;
+ typenames[i].name = PyString_AS_STRING(x);
+ typenames[i].type_index = lst1_length + i;
+
+ x = PyList_GET_ITEM(lst2, i * 2 + 1);
+ if (!CTypeDescr_Check(x))
+ goto bad_usage;
+ types[lst1_length + i] = x;
+ }
+ for (i = 0; i < lst1_length + lst2_length; i++) {
PyObject *x = (PyObject *)types[i];
Py_INCREF(x);
}
- Py_INCREF(lst1); /* to keep alive the strings in '.name' */
+ Py_INCREF(args); /* to keep alive the strings in '.name' */
Py_XDECREF(self->dynamic_types);
- self->dynamic_types = lst1;
+ self->dynamic_types = args;
self->types_builder->ctx.types = types;
- self->types_builder->num_types_imported = lst_length;
+ self->types_builder->num_types_imported = lst1_length + lst2_length;
self->types_builder->ctx.struct_unions = struct_unions;
- self->types_builder->ctx.num_struct_unions = lst_length;
+ self->types_builder->ctx.num_struct_unions = lst1_length;
+ self->types_builder->ctx.typenames = typenames;
+ self->types_builder->ctx.num_typenames = lst2_length;
Py_INCREF(Py_None);
return Py_None;
diff --git a/new/parse_c_type.c b/new/parse_c_type.c
index 426584b..05f38e8 100644
--- a/new/parse_c_type.c
+++ b/new/parse_c_type.c
@@ -56,7 +56,9 @@ static int is_space(char x)
static int is_ident_first(char x)
{
- return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_');
+ return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_' ||
+ x == '$'); /* '$' in names is supported here, for the struct
+ names invented by cparser */
}
static int is_digit(char x)
diff --git a/new/recompiler.py b/new/recompiler.py
index 65e429f..4acc7d0 100644
--- a/new/recompiler.py
+++ b/new/recompiler.py
@@ -508,8 +508,17 @@ class Recompiler:
_generate_cpy_union_collecttype = _generate_cpy_struct_collecttype
def _generate_cpy_struct_decl(self, tp, name):
- cname = tp.get_c_name('')
- self._struct_decl(tp, cname, cname.replace(' ', '_'))
+ cname = tp._get_c_name()
+ if ' ' in cname:
+ prefix, declname = cname.split(' ', 1)
+ else:
+ prefix, declname = '', cname
+ while declname.startswith('$'):
+ prefix += 'D'
+ declname = declname[1:]
+ approxname = prefix + '_' + declname
+ assert '$' not in approxname
+ self._struct_decl(tp, cname, approxname)
_generate_cpy_union_decl = _generate_cpy_struct_decl
def _generate_cpy_struct_ctx(self, tp, name, prefix='s'):
@@ -518,28 +527,6 @@ class Recompiler:
_generate_cpy_union_ctx = _generate_cpy_struct_ctx
# ----------
- # 'anonymous' declarations. These are produced for anonymous structs
- # or unions; the 'name' is obtained by a typedef.
-
- def _generate_cpy_anonymous_collecttype(self, tp, name):
- if isinstance(tp, model.EnumType):
- self._generate_cpy_enum_collecttype(tp, name)
- else:
- self._struct_collecttype(tp)
-
- def _generate_cpy_anonymous_decl(self, tp, name):
- if isinstance(tp, model.EnumType):
- self._generate_cpy_enum_decl(tp, name, '')
- else:
- self._struct_decl(tp, name, 'typedef_' + name)
-
- def _generate_cpy_anonymous_ctx(self, tp, name):
- if isinstance(tp, model.EnumType):
- self._generate_cpy_enum_ctx(tp, name, '')
- else:
- self._struct_ctx(tp, name, 'typedef_' + name)
-
- # ----------
# constants, declared with "static const ..."
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
diff --git a/new/test_dlopen.py b/new/test_dlopen.py
index b1348f9..633c731 100644
--- a/new/test_dlopen.py
+++ b/new/test_dlopen.py
@@ -19,6 +19,34 @@ def test_cdef_struct_union():
assert ffi.sizeof("union bar_s") == 4
assert ffi.sizeof("struct foo_s") == 4
+def test_cdef_struct_typename_1():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } t1; typedef struct { t1* m; } t2;")
+ assert ffi.sizeof("t2") == ffi.sizeof("void *")
+ assert ffi.sizeof("t1") == 4
+
+def test_cdef_struct_typename_2():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } *p1; typedef struct { p1 m; } *p2;")
+ p2 = ffi.new("p2")
+ assert ffi.sizeof(p2[0]) == ffi.sizeof("void *")
+ assert ffi.sizeof(p2[0].m) == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_1():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } t1; struct foo_s { t1* m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_2():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } *p1; struct foo_s { p1 m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_3():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } **pp; struct foo_s { pp m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
def test_math_sin():
py.test.skip("XXX redo!")
ffi = FFI()