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