[pypy-commit] cffi verifier2: Test and fix

arigo noreply at buildbot.pypy.org
Fri Jul 27 18:55:24 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: verifier2
Changeset: r729:34052d659eac
Date: 2012-07-27 18:47 +0200
http://bitbucket.org/cffi/cffi/changeset/34052d659eac/

Log:	Test and fix

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -1730,7 +1730,7 @@
 #endif
         }
         if (convert_from_object(data, argtype, obj) < 0) {
-            if (CData_Check(obj) && argtype->ct_flags & CT_POINTER &&
+            if (CData_Check(obj) && (argtype->ct_flags & CT_POINTER) &&
                    argtype->ct_itemdescr == ((CDataObject *)obj)->c_type) {
                 /* special case to make the life of verifier.py easier:
                    if the formal argument type is 'struct foo *' but
@@ -3908,6 +3908,11 @@
     return result;
 }
 
+static short _testfunc18(struct _testfunc7_s *ptr)
+{
+    return ptr->a1 + ptr->a2;
+}
+
 static PyObject *b__testfunc(PyObject *self, PyObject *args)
 {
     /* for testing only */
@@ -3934,6 +3939,7 @@
     case 15: f = &_testfunc15; break;
     case 16: f = &_testfunc16; break;
     case 17: f = &_testfunc17; break;
+    case 18: f = &_testfunc18; break;
     default:
         PyErr_SetNone(PyExc_ValueError);
         return NULL;
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -786,6 +786,22 @@
     res = f(x[0])
     assert res == -4042 + ord('A')
 
+def test_call_function_18():
+    BChar = new_primitive_type("char")
+    BShort = new_primitive_type("short")
+    BStruct = new_struct_type("foo")
+    BStructPtr = new_pointer_type(BStruct)
+    complete_struct_or_union(BStruct, [('a1', BChar, -1),
+                                       ('a2', BShort, -1)])
+    BFunc18 = new_function_type((BStructPtr,), BShort, False)
+    f = cast(BFunc18, _testfunc(18))
+    x = newp(BStructPtr, {'a1': 'A', 'a2': -4042})
+    # test the exception that allows us to pass a 'struct foo' where the
+    # function really expects a 'struct foo *'.
+    res = f(x[0])
+    assert res == -4042 + ord('A')
+    assert res == f(x)
+
 def test_call_function_9():
     BInt = new_primitive_type("int")
     BFunc9 = new_function_type((BInt,), BInt, True)    # vararg
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -227,19 +227,31 @@
         if tp.ellipsis:
             newfunction = self._load_constant(False, tp, name, module)
         else:
+            indirections = []
             if any(isinstance(type, model.StructOrUnion) for type in tp.args):
                 indirect_args = []
                 for i, type in enumerate(tp.args):
                     if isinstance(type, model.StructOrUnion):
                         type = model.PointerType(type)
+                        indirections.append((i, type))
                     indirect_args.append(type)
                 tp = model.FunctionPtrType(tuple(indirect_args),
                                            tp.result, tp.ellipsis)
             BFunc = self.ffi._get_cached_btype(tp)
             wrappername = '_cffi_f_%s' % name
             newfunction = module.load_function(BFunc, wrappername)
+            for i, type in indirections:
+                newfunction = self._make_struct_wrapper(newfunction, i, type)
         setattr(library, name, newfunction)
 
+    def _make_struct_wrapper(self, oldfunc, i, tp):
+        backend = self.ffi._backend
+        BType = self.ffi._get_cached_btype(tp)
+        def newfunc(*args):
+            args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
+            return oldfunc(*args)
+        return newfunc
+
     # ----------
     # named structs
 
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -583,6 +583,7 @@
     """)
     s = ffi.new("struct foo_s *", [100, 1])
     assert lib.foo(s[0]) == 99
+    assert lib.foo([100, 1]) == 99
 
 def test_autofilled_struct_as_argument_dynamic():
     ffi = FFI()


More information about the pypy-commit mailing list