Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r1077:54980638b1bc
Date: 2012-11-29 17:39 -0800
http://bitbucket.org/cffi/cffi/changeset/54980638b1bc/

Log:    Improve error reporting for functions that return an opaque type.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3843,8 +3843,12 @@
     }
     if ((fresult->ct_size < 0 && !(fresult->ct_flags & CT_VOID)) ||
         (fresult->ct_flags & CT_ARRAY)) {
-        PyErr_Format(PyExc_TypeError, "invalid result type: '%s'",
-                     fresult->ct_name);
+        char *msg;
+        if (fresult->ct_flags & CT_IS_OPAQUE)
+            msg = "result type '%s' is opaque";
+        else
+            msg = "invalid result type: '%s'";
+        PyErr_Format(PyExc_TypeError, msg, fresult->ct_name);
         return NULL;
     }
 
diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py
--- a/cffi/vengine_cpy.py
+++ b/cffi/vengine_cpy.py
@@ -221,7 +221,7 @@
             tovar, tp.get_c_name(''), errvalue))
         self._prnt('    %s;' % errcode)
 
-    def _convert_expr_from_c(self, tp, var):
+    def _convert_expr_from_c(self, tp, var, where):
         if isinstance(tp, model.PrimitiveType):
             if tp.is_integer_type():
                 if tp.is_signed_type():
@@ -240,6 +240,9 @@
             return '_cffi_from_c_deref((char *)%s, _cffi_type(%d))' % (
                 var, self._gettypenum(tp))
         elif isinstance(tp, model.StructType):
+            if tp.fldnames is None:
+                raise TypeError("'%s' is used as %s, but is opaque" % (
+                    tp._get_c_name(''), where))
             return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
                 var, self._gettypenum(tp))
         elif isinstance(tp, model.EnumType):
@@ -325,7 +328,8 @@
         #
         if result_code:
             prnt('  return %s;' %
-                 self._convert_expr_from_c(tp.result, 'result'))
+                 self._convert_expr_from_c(tp.result, 'result',
+                                           'result of %s()' % name))
         else:
             prnt('  Py_INCREF(Py_None);')
             prnt('  return Py_None;')
@@ -529,7 +533,8 @@
             else:
                 realexpr = name
             prnt('  i = (%s);' % (realexpr,))
-            prnt('  o = %s;' % (self._convert_expr_from_c(tp, 'i'),))
+            prnt('  o = %s;' % (self._convert_expr_from_c(tp, 'i',
+                                                'type of %s' % name),))
             assert delayed
         else:
             prnt('  if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name))
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -154,7 +154,11 @@
                     indirect_args.append(type)
                 tp = model.FunctionPtrType(tuple(indirect_args),
                                            tp.result, tp.ellipsis)
-            BFunc = self.ffi._get_cached_btype(tp)
+            try:
+                BFunc = self.ffi._get_cached_btype(tp)
+            except TypeError, e:
+                msg = 'function %s(): %s' % (name, e)
+                raise TypeError(msg)
             wrappername = '_cffi_f_%s' % name
             newfunction = module.load_function(BFunc, wrappername)
             for i, type in indirections:
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1378,3 +1378,22 @@
     ffi.cdef("int fooarray[...];")
     lib = ffi.verify("int fooarray[50];")
     assert repr(lib.fooarray).startswith("<cdata 'int *'")
+
+def test_struct_containing_struct():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
+    ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
+    #
+    ffi = FFI()
+    ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
+    ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
+
+def test_struct_returned_by_func():
+    ffi = FFI()
+    ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
+    e = py.test.raises(TypeError, ffi.verify,
+                       "typedef struct { int x; } foo_t; "
+                       "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
+    assert str(e.value) in [
+        "'foo_t' is used as result of myfunc(), but is opaque",
+        "function myfunc(): result type 'struct $foo_t' is opaque"]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to