diff options
Diffstat (limited to 'cffi')
-rw-r--r-- | cffi/cparser.py | 18 | ||||
-rw-r--r-- | cffi/model.py | 7 | ||||
-rw-r--r-- | cffi/vengine_cpy.py | 4 | ||||
-rw-r--r-- | cffi/vengine_gen.py | 4 |
4 files changed, 24 insertions, 9 deletions
diff --git a/cffi/cparser.py b/cffi/cparser.py index ea27c48..d7069a7 100644 --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -395,7 +395,8 @@ class Parser(object): realtype = self._get_unknown_ptr_type(decl) else: realtype, quals = self._get_type_and_quals( - decl.type, name=decl.name, partial_length_ok=True) + decl.type, name=decl.name, partial_length_ok=True, + typedef_example="*(%s *)0" % (decl.name,)) self._declare('typedef ' + decl.name, realtype, quals=quals) elif decl.__class__.__name__ == 'Pragma': pass # skip pragma, only in pycparser 2.15 @@ -562,7 +563,8 @@ class Parser(object): return model.NamedPointerType(type, declname, quals) return model.PointerType(type, quals) - def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False): + def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False, + typedef_example=None): # first, dereference typedefs, if we have it already parsed, we're good if (isinstance(typenode, pycparser.c_ast.TypeDecl) and isinstance(typenode.type, pycparser.c_ast.IdentifierType) and @@ -579,8 +581,18 @@ class Parser(object): else: length = self._parse_constant( typenode.dim, partial_length_ok=partial_length_ok) + # a hack: in 'typedef int foo_t[...][...];', don't use '...' as + # the length but use directly the C expression that would be + # generated by recompiler.py. This lets the typedef be used in + # many more places within recompiler.py + if typedef_example is not None: + if length == '...': + length = '_cffi_array_len(%s)' % (typedef_example,) + typedef_example = "*" + typedef_example + # tp, quals = self._get_type_and_quals(typenode.type, - partial_length_ok=partial_length_ok) + partial_length_ok=partial_length_ok, + typedef_example=typedef_example) return model.ArrayType(tp, length), quals # if isinstance(typenode, pycparser.c_ast.PtrDecl): diff --git a/cffi/model.py b/cffi/model.py index 5f1b0d2..ad1c176 100644 --- a/cffi/model.py +++ b/cffi/model.py @@ -307,11 +307,14 @@ class ArrayType(BaseType): self.c_name_with_marker = ( self.item.c_name_with_marker.replace('&', brackets)) + def length_is_unknown(self): + return isinstance(self.length, str) + def resolve_length(self, newlength): return ArrayType(self.item, newlength) def build_backend_type(self, ffi, finishlist): - if self.length == '...': + if self.length_is_unknown(): raise CDefError("cannot render the type %r: unknown length" % (self,)) self.item.get_cached_btype(ffi, finishlist) # force the item BType @@ -430,7 +433,7 @@ class StructOrUnion(StructOrUnionOrEnum): fsize = fieldsize[i] ftype = self.fldtypes[i] # - if isinstance(ftype, ArrayType) and ftype.length == '...': + if isinstance(ftype, ArrayType) and ftype.length_is_unknown(): # fix the length to match the total size BItemType = ftype.item.get_cached_btype(ffi, finishlist) nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py index cb344ce..6de0df0 100644 --- a/cffi/vengine_cpy.py +++ b/cffi/vengine_cpy.py @@ -762,7 +762,7 @@ class VCPythonEngine(object): if isinstance(tp, model.ArrayType): tp_ptr = model.PointerType(tp.item) self._generate_cpy_const(False, name, tp, vartp=tp_ptr, - size_too = (tp.length == '...')) + size_too = tp.length_is_unknown()) else: tp_ptr = model.PointerType(tp) self._generate_cpy_const(False, name, tp_ptr, category='var') @@ -774,7 +774,7 @@ class VCPythonEngine(object): value = getattr(library, name) if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the # sense that "a=..." is forbidden - if tp.length == '...': + if tp.length_is_unknown(): assert isinstance(value, tuple) (value, size) = value BItemType = self.ffi._get_cached_btype(tp.item) diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py index a64ff64..2642152 100644 --- a/cffi/vengine_gen.py +++ b/cffi/vengine_gen.py @@ -565,7 +565,7 @@ class VGenericEngine(object): def _generate_gen_variable_decl(self, tp, name): if isinstance(tp, model.ArrayType): - if tp.length == '...': + if tp.length_is_unknown(): prnt = self._prnt funcname = '_cffi_sizeof_%s' % (name,) self.export_symbols.append(funcname) @@ -584,7 +584,7 @@ class VGenericEngine(object): def _loaded_gen_variable(self, tp, name, module, library): if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the # sense that "a=..." is forbidden - if tp.length == '...': + if tp.length_is_unknown(): funcname = '_cffi_sizeof_%s' % (name,) BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] function = module.load_function(BFunc, funcname) |