Commits

Armin Rigo committed 74e2a55

Delete all the mess about _need_size. Instead, document the "proper"
solution (found thanks to discussions with O.Esser)

Comments (0)

Files changed (3)

 
     def _collect_types(self):
         self._typesdict = {}
-        self._need_size = []
         self._generate("collecttype")
 
     def _do_collect_type(self, tp):
                 tp not in self._typesdict):
             num = len(self._typesdict)
             self._typesdict[tp] = num
-            if isinstance(tp, model.StructOrUnion):
-                self._need_size.append(tp)
 
     def _write_source(self, file=None):
         must_close = (file is None)
         library = FFILibrary()
         sz = module._cffi_setup(lst, ffiplatform.VerificationError, library)
         #
-        # adjust the size of some structs based on what 'sz' returns
-        if self._need_size:
-            assert len(sz) == 2 * len(self._need_size)
-            for i, tp in enumerate(self._need_size):
-                size, alignment = sz[i*2], sz[i*2+1]
-                BType = self.ffi._get_cached_btype(tp)
-                if tp.fldtypes is None:
-                    # an opaque struct: give it now a size and alignment
-                    self.ffi._backend.complete_struct_or_union(BType, [], None,
-                                                               size, alignment)
-                else:
-                    assert size == self.ffi.sizeof(BType)
-                    assert alignment == self.ffi.alignof(BType)
-        #
         # finally, call the loaded_cpy_xxx() functions.  This will perform
         # the final adjustments, like copying the Python->C wrapper
         # functions from the module to the 'library' object, and setting
         prnt('{')
         prnt('  if (%s < 0)' % self._chained_list_constants[True])
         prnt('    return NULL;')
-        # produce the size of the opaque structures that need it.
-        # So far, limited to the structures used as function arguments
-        # or results.  (These might not be real structures at all, but
-        # instead just some integer handles; but it works anyway)
-        if self._need_size:
-            N = len(self._need_size)
-            prnt('  else {')
-            for i, tp in enumerate(self._need_size):
-                prnt('    struct _cffi_aligncheck%d { char x; %s; };' % (
-                    i, tp.get_c_name(' y')))
-            prnt('    static Py_ssize_t content[] = {')
-            for i, tp in enumerate(self._need_size):
-                prnt('      sizeof(%s),' % tp.get_c_name())
-                prnt('      offsetof(struct _cffi_aligncheck%d, y),' % i)
-            prnt('    };')
-            prnt('    int i;')
-            prnt('    PyObject *o, *lst = PyList_New(%d);' % (2*N,))
-            prnt('    if (lst == NULL)')
-            prnt('      return NULL;')
-            prnt('    for (i=0; i<%d; i++) {' % (2*N,))
-            prnt('      o = PyInt_FromSsize_t(content[i]);')
-            prnt('      if (o == NULL) {')
-            prnt('        Py_DECREF(lst);')
-            prnt('        return NULL;')
-            prnt('      }')
-            prnt('      PyList_SET_ITEM(lst, i, o);')
-            prnt('    }')
-            prnt('    return lst;')
-            prnt('  }')
-        else:
-            prnt('  Py_INCREF(Py_None);')
-            prnt('  return Py_None;')
+        prnt('  Py_INCREF(Py_None);')
+        prnt('  return Py_None;')
         prnt('}')
 
 cffimod_header = r'''

doc/source/index.rst

 
 *  unknown types: the syntax "``typedef ... foo_t;``" declares the type
    ``foo_t`` as opaque.  Useful mainly for when the API takes and returns
-   ``foo_t *`` without you needing to look inside the ``foo_t``.
+   ``foo_t *`` without you needing to look inside the ``foo_t``.  Note that
+   such an opaque struct has no known size, which prevents some operations
+   from working (mostly like in C).  In some cases you need to say that
+   ``foo_t`` is not opaque, but you just don't know any field in it; then
+   you would use "``typedef struct { ...; } foo_t;``".
 
 *  array lengths: when used as structure fields, arrays can have an
    unspecified length, as in "``int n[];``" or "``int n[...];``.

testing/test_verify.py

     assert lib.foo_func(lib.BB) == "BB"
 
 def test_opaque_integer_as_function_result():
+    # XXX bad abuse of "struct { ...; }".  It only works a bit by chance
+    # anyway.  XXX think about something better :-(
     ffi = FFI()
     ffi.cdef("""
-        typedef ... handle_t;
+        typedef struct { ...; } handle_t;
         handle_t foo(void);
     """)
     lib = ffi.verify("""