Author: Antonio Cuni <[email protected]>
Branch: ffistruct
Changeset: r55089:5881f062c4f5
Date: 2012-05-14 21:35 +0200
http://bitbucket.org/pypy/pypy/changeset/5881f062c4f5/
Log: split the _StructDescr initialization in two phases: instantiation
and field definition. This allow to get its ffitype before it's
actually complete, in case it's necessary to take a pointer to it
diff --git a/pypy/module/_ffi/interp_ffitype.py
b/pypy/module/_ffi/interp_ffitype.py
--- a/pypy/module/_ffi/interp_ffitype.py
+++ b/pypy/module/_ffi/interp_ffitype.py
@@ -4,6 +4,7 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.error import OperationError
class W_FFIType(Wrappable):
@@ -24,13 +25,22 @@
raise ValueError("Operation not permitted on an incomplete type")
return self._ffitype
+ def set_ffitype(self, ffitype):
+ if self._ffitype:
+ raise ValueError("The _ffitype is already set")
+ self._ffitype = ffitype
+
def descr_deref_pointer(self, space):
if self.w_pointer_to is None:
return space.w_None
return self.w_pointer_to
def descr_sizeof(self, space):
- return space.wrap(self.sizeof())
+ try:
+ return space.wrap(self.sizeof())
+ except ValueError:
+ msg = "Operation not permitted on an incomplete type"
+ raise OperationError(space.w_ValueError, space.wrap(msg))
def sizeof(self):
return intmask(self.get_ffitype().c_size)
diff --git a/pypy/module/_ffi/interp_struct.py
b/pypy/module/_ffi/interp_struct.py
--- a/pypy/module/_ffi/interp_struct.py
+++ b/pypy/module/_ffi/interp_struct.py
@@ -41,16 +41,34 @@
class W__StructDescr(Wrappable):
- def __init__(self, space, name, fields_w, ffistruct):
+ def __init__(self, space, name):
self.space = space
- self.ffistruct = ffistruct
- self.w_ffitype = W_FFIType('struct %s' % name, ffistruct.ffistruct,
None)
+ self.w_ffitype = W_FFIType('struct %s' % name, clibffi.FFI_TYPE_NULL,
None)
+ self.fields_w = None
+ self.name2w_field = {}
+
+ def define_fields(self, space, w_fields):
+ if self.fields_w is not None:
+ raise operationerrfmt(space.w_ValueError,
+ "%s's fields has already been defined",
+ self.w_ffitype.name)
+ space = self.space
+ fields_w = space.fixedview(w_fields)
+ # note that the fields_w returned by compute_size_and_alignement has a
+ # different annotation than the original: list(W_Root) vs list(W_Field)
+ size, alignment, fields_w = compute_size_and_alignement(space,
fields_w)
self.fields_w = fields_w
- self.name2w_field = {}
+ field_types = [] # clibffi's types
for w_field in fields_w:
+ field_types.append(w_field.w_ffitype.get_ffitype())
self.name2w_field[w_field.name] = w_field
+ self.ffistruct = clibffi.make_struct_ffitype_e(size, alignment,
field_types)
+ self.w_ffitype.set_ffitype(self.ffistruct.ffistruct)
def allocate(self, space):
+ if self.fields_w is None:
+ raise operationerrfmt(space.w_ValueError, "%s has an incomplete
type",
+ self.w_ffitype.name)
return W__StructInstance(self)
@jit.elidable_promote('0')
@@ -69,16 +87,11 @@
@unwrap_spec(name=str)
-def descr_new_structdescr(space, w_type, name, w_fields):
- fields_w = space.fixedview(w_fields)
- # note that the fields_w returned by compute_size_and_alignement has a
- # different annotation than the original: list(W_Root) vs list(W_Field)
- size, alignment, fields_w = compute_size_and_alignement(space, fields_w)
- field_types = [] # clibffi's types
- for w_field in fields_w:
- field_types.append(w_field.w_ffitype.get_ffitype())
- ffistruct = clibffi.make_struct_ffitype_e(size, alignment, field_types)
- return W__StructDescr(space, name, fields_w, ffistruct)
+def descr_new_structdescr(space, w_type, name, w_fields=None):
+ descr = W__StructDescr(space, name)
+ if w_fields is not space.w_None:
+ descr.define_fields(w_fields)
+ return descr
def round_up(size, alignment):
return (size + alignment - 1) & -alignment
@@ -106,6 +119,7 @@
'_StructDescr',
__new__ = interp2app(descr_new_structdescr),
ffitype = interp_attrproperty('w_ffitype', W__StructDescr),
+ define_fields = interp2app(W__StructDescr.define_fields),
allocate = interp2app(W__StructDescr.allocate),
)
diff --git a/pypy/module/_ffi/test/test_struct.py
b/pypy/module/_ffi/test/test_struct.py
--- a/pypy/module/_ffi/test/test_struct.py
+++ b/pypy/module/_ffi/test/test_struct.py
@@ -228,6 +228,25 @@
mem = self.read_raw_mem(struct.getaddr(), 'c_float', 1)
assert mem == [123.5]
+ def test_define_fields(self):
+ from _ffi import _StructDescr, Field, types
+ longsize = types.slong.sizeof()
+ fields = [
+ Field('x', types.slong),
+ Field('y', types.slong),
+ ]
+ descr = _StructDescr('foo')
+ assert descr.ffitype.name == 'struct foo'
+ assert repr(descr.ffitype) == '<ffi type struct foo (incomplete)>'
+ raises(ValueError, "descr.ffitype.sizeof()")
+ raises(ValueError, "descr.allocate()")
+ #
+ descr.define_fields(fields)
+ assert repr(descr.ffitype) == '<ffi type struct foo>'
+ assert descr.ffitype.sizeof() == longsize*2
+ raises(ValueError, "descr.define_fields(fields)")
+
+
def test_compute_shape(self):
from _ffi import Structure, Field, types
class Point(Structure):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit