[pypy-commit] pypy cffi-1.0: Finish to port the changes to c/_cffi_backend

arigo noreply at buildbot.pypy.org
Thu May 7 16:02:25 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77178:3fe66e2f8736
Date: 2015-05-07 16:02 +0200
http://bitbucket.org/pypy/pypy/changeset/3fe66e2f8736/

Log:	Finish to port the changes to c/_cffi_backend

diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -292,7 +292,8 @@
         # here, so better safe (and forbid it) than sorry (and maybe
         # crash).
         space = self.space
-        if ctype.custom_field_pos:
+        ctype.force_lazy_struct()
+        if ctype._custom_field_pos:
             raise OperationError(space.w_TypeError,
                                  space.wrap(
                "cannot pass as an argument a struct that was completed "
@@ -302,7 +303,7 @@
         # walk the fields, expanding arrays into repetitions; first,
         # only count how many flattened fields there are
         nflat = 0
-        for i, cf in enumerate(ctype.fields_list):
+        for i, cf in enumerate(ctype._fields_list):
             if cf.is_bitfield():
                 raise oefmt(space.w_NotImplementedError,
                     "ctype '%s' not supported as argument or return value"
@@ -334,7 +335,7 @@
 
         # fill it with the ffi types of the fields
         nflat = 0
-        for i, cf in enumerate(ctype.fields_list):
+        for i, cf in enumerate(ctype._fields_list):
             flat = 1
             ct = cf.ctype
             while isinstance(ct, ctypearray.W_CTypeArray):
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -199,9 +199,11 @@
             # a W_CDataPtrToStruct object which has a strong reference
             # to a W_CDataNewOwning that really contains the structure.
             #
-            if ctitem.with_var_array and not space.is_w(w_init, space.w_None):
-                datasize = ctitem.convert_struct_from_object(
-                    lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
+            if not space.is_w(w_init, space.w_None):
+                ctitem.force_lazy_struct()
+                if ctitem._with_var_array:
+                    datasize = ctitem.convert_struct_from_object(
+                        lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
             #
             cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem)
             ptr = cdatastruct.unsafe_escaping_ptr()
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -16,24 +16,40 @@
 
 
 class W_CTypeStructOrUnion(W_CType):
-    _immutable_fields_ = ['alignment?', 'fields_list?[*]', 'fields_dict?',
-                          'custom_field_pos?', 'with_var_array?']
+    _immutable_fields_ = ['alignment?', '_fields_list?[*]', '_fields_dict?',
+                          '_custom_field_pos?', '_with_var_array?']
+
+    # three possible states:
+    # - "opaque": for opaque C structs; self.size < 0.
+    # - "lazy": for non-opaque C structs whose _fields_list, _fields_dict,
+    #       _custom_field_pos and _with_var_array are not filled yet; can be
+    #       filled by calling force_lazy_struct().
+    #       (But self.size and .alignment are already set and won't change.)
+    # - "forced": for non-opaque C structs which are fully ready.
+
     # fields added by complete_struct_or_union():
     alignment = -1
-    fields_list = None
-    fields_dict = None
-    custom_field_pos = False
-    with_var_array = False
+    _fields_list = None
+    _fields_dict = None
+    _custom_field_pos = False
+    _with_var_array = False
 
     def __init__(self, space, name):
         W_CType.__init__(self, space, -1, name, len(name))
 
     def check_complete(self, w_errorcls=None):
-        if self.fields_dict is None:
+        # Check ONLY that are are not opaque.  Complain if we are.
+        if self.size < 0:
             space = self.space
             raise oefmt(w_errorcls or space.w_TypeError,
                         "'%s' is opaque or not completed yet", self.name)
 
+    def force_lazy_struct(self, w_errorcls=None):
+        # Force a "lazy" struct to become "forced"; complain if we are "opaque".
+        if self._fields_list is None:
+            self.check_complete()
+            XXXXX
+
     def _alignof(self):
         self.check_complete(w_errorcls=self.space.w_ValueError)
         return self.alignment
@@ -43,9 +59,10 @@
             space = self.space
             if self.size < 0:
                 return space.w_None
-            result = [None] * len(self.fields_list)
-            for fname, field in self.fields_dict.iteritems():
-                i = self.fields_list.index(field)
+            self.force_lazy_struct()
+            result = [None] * len(self._fields_list)
+            for fname, field in self._fields_dict.iteritems():
+                i = self._fields_list.index(field)
                 result[i] = space.newtuple([space.wrap(fname),
                                             space.wrap(field)])
             return space.newlist(result)
@@ -65,10 +82,10 @@
         return ob
 
     def typeoffsetof_field(self, fieldname, following):
-        self.check_complete()
+        self.force_lazy_struct()
         space = self.space
         try:
-            cfield = self.fields_dict[fieldname]
+            cfield = self._fields_dict[fieldname]
         except KeyError:
             raise OperationError(space.w_KeyError, space.wrap(fieldname))
         if cfield.bitshift >= 0:
@@ -95,19 +112,20 @@
         lambda self, cdata, w_ob, optvarsize: jit.isvirtual(w_ob)
     )
     def convert_struct_from_object(self, cdata, w_ob, optvarsize):
+        self.force_lazy_struct()
         self._check_only_one_argument_for_union(w_ob)
 
         space = self.space
         if (space.isinstance_w(w_ob, space.w_list) or
             space.isinstance_w(w_ob, space.w_tuple)):
             lst_w = space.listview(w_ob)
-            if len(lst_w) > len(self.fields_list):
+            if len(lst_w) > len(self._fields_list):
                 raise oefmt(space.w_ValueError,
                             "too many initializers for '%s' (got %d)",
                             self.name, len(lst_w))
             for i in range(len(lst_w)):
-                optvarsize = self.fields_list[i].write_v(cdata, lst_w[i],
-                                                         optvarsize)
+                optvarsize = self._fields_list[i].write_v(cdata, lst_w[i],
+                                                          optvarsize)
             return optvarsize
 
         elif space.isinstance_w(w_ob, space.w_dict):
@@ -116,7 +134,7 @@
                 w_key = lst_w[i]
                 key = space.str_w(w_key)
                 try:
-                    cf = self.fields_dict[key]
+                    cf = self._fields_dict[key]
                 except KeyError:
                     space.raise_key_error(w_key)
                     assert 0
@@ -133,10 +151,14 @@
 
     @jit.elidable
     def _getcfield_const(self, attr):
-        return self.fields_dict[attr]
+        return self._fields_dict[attr]
 
     def getcfield(self, attr):
-        if self.fields_dict is not None:
+        ready = self._fields_dict is not None
+        if not ready and self.size >= 0:
+            self.force_lazy_struct()
+            ready = True
+        if ready:
             self = jit.promote(self)
             attr = jit.promote_string(attr)
             try:
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -349,9 +349,10 @@
                     isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
                 # a nested anonymous struct or union
                 srcfield2names = {}
-                for name, srcfld in ftype.fields_dict.items():
+                ftype.force_lazy_struct()
+                for name, srcfld in ftype._fields_dict.items():
                     srcfield2names[srcfld] = name
-                for srcfld in ftype.fields_list:
+                for srcfld in ftype._fields_list:
                     fld = srcfld.make_shifted(boffset // 8)
                     fields_list.append(fld)
                     try:
@@ -492,10 +493,10 @@
 
     w_ctype.size = totalsize
     w_ctype.alignment = totalalignment
-    w_ctype.fields_list = fields_list[:]
-    w_ctype.fields_dict = fields_dict
-    w_ctype.custom_field_pos = custom_field_pos
-    w_ctype.with_var_array = with_var_array
+    w_ctype._fields_list = fields_list[:]
+    w_ctype._fields_dict = fields_dict
+    w_ctype._custom_field_pos = custom_field_pos
+    w_ctype._with_var_array = with_var_array
 
 # ____________________________________________________________
 


More information about the pypy-commit mailing list