Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r58814:be31229abe7d
Date: 2012-11-09 17:48 +0100
http://bitbucket.org/pypy/pypy/changeset/be31229abe7d/

Log:    Import and fix cffi/b22bc0909265.

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,24 +292,42 @@
             if ctype.size <= 8:
                 return clibffi.ffi_type_sint64
 
-        # allocate an array of (n + 1) ffi_types
-        n = len(ctype.fields_list)
-        elements = self.fb_alloc(rffi.sizeof(FFI_TYPE_P) * (n + 1))
-        elements = rffi.cast(FFI_TYPE_PP, elements)
-
-        # fill it with the ffi types of the fields
+        # 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):
             if cf.is_bitfield():
                 raise OperationError(space.w_NotImplementedError,
                     space.wrap("cannot pass as argument or return value "
                                "a struct with bit fields"))
-            ffi_subtype = self.fb_fill_type(cf.ctype, False)
+            flat = 1
+            ct = cf.ctype
+            while isinstance(ct, ctypearray.W_CTypeArray):
+                flat *= ct.length
+                ct = ct.ctitem
+            nflat += flat
+
+        # allocate an array of (nflat + 1) ffi_types
+        elements = self.fb_alloc(rffi.sizeof(FFI_TYPE_P) * (nflat + 1))
+        elements = rffi.cast(FFI_TYPE_PP, elements)
+
+        # fill it with the ffi types of the fields
+        nflat = 0
+        for i, cf in enumerate(ctype.fields_list):
+            flat = 1
+            ct = cf.ctype
+            while isinstance(ct, ctypearray.W_CTypeArray):
+                flat *= ct.length
+                ct = ct.ctitem
+            ffi_subtype = self.fb_fill_type(ct, False)
             if elements:
-                elements[i] = ffi_subtype
+                for j in range(flat):
+                    elements[nflat] = ffi_subtype
+                    nflat += 1
 
         # zero-terminate the array
         if elements:
-            elements[n] = lltype.nullptr(FFI_TYPE_P.TO)
+            elements[nflat] = lltype.nullptr(FFI_TYPE_P.TO)
 
         # allocate and fill an ffi_type for the struct itself
         ffistruct = self.fb_alloc(rffi.sizeof(FFI_TYPE))
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -923,6 +923,20 @@
     lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
     assert res == sum(lst)
 
+def test_call_function_22():
+    BInt = new_primitive_type("int")
+    BArray10 = new_array_type(new_pointer_type(BInt), 10)
+    BStruct = new_struct_type("foo")
+    BStructP = new_pointer_type(BStruct)
+    complete_struct_or_union(BStruct, [('a', BArray10, -1)])
+    BFunc22 = new_function_type((BStruct, BStruct), BStruct, False)
+    f = cast(BFunc22, _testfunc(22))
+    p1 = newp(BStructP, {'a': range(100, 110)})
+    p2 = newp(BStructP, {'a': range(1000, 1100, 10)})
+    res = f(p1[0], p2[0])
+    for i in range(10):
+        assert res.a[i] == p1.a[i] - p2.a[i]
+
 def test_call_function_9():
     BInt = new_primitive_type("int")
     BFunc9 = new_function_type((BInt,), BInt, True)    # vararg
diff --git a/pypy/module/_cffi_backend/test/_test_lib.c 
b/pypy/module/_cffi_backend/test/_test_lib.c
--- a/pypy/module/_cffi_backend/test/_test_lib.c
+++ b/pypy/module/_cffi_backend/test/_test_lib.c
@@ -161,6 +161,17 @@
             (inlined.j << 9));
 }
 
+struct _testfunc22_s { int a[10]; };
+static struct _testfunc22_s _testfunc22(struct _testfunc22_s s1,
+                                        struct _testfunc22_s s2)
+{
+    struct _testfunc22_s result;
+    int i;
+    for (i=0; i<10; i++)
+        result.a[i] = s1.a[i] - s2.a[i];
+    return result;
+}
+
 DLLEXPORT void *gettestfunc(int num)
 {
     void *f;
@@ -187,6 +198,7 @@
     case 19: f = &_testfunc19; break;
     case 20: f = &_testfunc20; break;
     case 21: f = &_testfunc21; break;
+    case 22: f = &_testfunc22; break;
     default:
         return NULL;
     }
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to