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