Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r2170:792c0cbe632d
Date: 2015-06-07 16:00 +0200
http://bitbucket.org/cffi/cffi/changeset/792c0cbe632d/

Log:    Support "[][...]", "[5][...]", etc.

diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -337,7 +337,7 @@
                 length = self._parse_constant(
                     typenode.dim, partial_length_ok=partial_length_ok)
             tp = self._get_type(typenode.type,
-                                partial_length_ok=(length == '...'))
+                                partial_length_ok=partial_length_ok)
             return model.ArrayType(tp, length)
         #
         if isinstance(typenode, pycparser.c_ast.PtrDecl):
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -749,10 +749,12 @@
     # named structs or unions
 
     def _field_type(self, tp_struct, field_name, tp_field):
-        if isinstance(tp_field, model.ArrayType) and tp_field.length == '...':
-            ptr_struct_name = tp_struct.get_c_name('*')
-            actual_length = '_cffi_array_len(((%s)0)->%s)' % (
-                ptr_struct_name, field_name)
+        if isinstance(tp_field, model.ArrayType):
+            actual_length = tp_field.length
+            if actual_length == '...':
+                ptr_struct_name = tp_struct.get_c_name('*')
+                actual_length = '_cffi_array_len(((%s)0)->%s)' % (
+                    ptr_struct_name, field_name)
             tp_item = self._field_type(tp_struct, '%s[0]' % field_name,
                                        tp_field.item)
             tp_field = model.ArrayType(tp_item, actual_length)
@@ -1055,8 +1057,10 @@
     # global variables
 
     def _global_type(self, tp, global_name):
-        if isinstance(tp, model.ArrayType) and tp.length == '...':
-            actual_length = '_cffi_array_len(%s)' % (global_name,)
+        if isinstance(tp, model.ArrayType):
+            actual_length = tp.length
+            if actual_length == '...':
+                actual_length = '_cffi_array_len(%s)' % (global_name,)
             tp_item = self._global_type(tp.item, '%s[0]' % global_name)
             tp = model.ArrayType(tp_item, actual_length)
         return tp
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -3,6 +3,19 @@
 ======================
 
 
+1.1.2
+=====
+
+* Out-of-line mode: ``int a[][...];`` can be used to declare a structure
+  field or global variable which is simultanously of total length
+  unknown to the C compiler (the ``[]`` part), but each element is an
+  array of N integers, where the value of N *is* known to the C compiler
+  (the ``int [...]`` part around).  Similarly, ``int a[5][...];`` is
+  supported (but probably less useful).  Remember that in the order of
+  the C syntax, it means an array of 5 things, each of which is an array
+  of N integers---and ask the C compiler for the value of N.
+
+
 1.1.1
 =====
 
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -924,6 +924,18 @@
     assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
     assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
 
+def test_struct_array_guess_length_3():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { int a[][...]; };")
+    lib = verify(ffi, 'test_struct_array_guess_length_3',
+                 "struct foo_s { int x; int a[5][7]; int y; };")
+    assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int')
+    s = ffi.new("struct foo_s *")
+    assert ffi.typeof(s.a) == ffi.typeof("int(*)[7]")
+    assert s.a[4][6] == 0
+    py.test.raises(IndexError, 's.a[4][7]')
+    assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
+
 def test_global_var_array_2():
     ffi = FFI()
     ffi.cdef("int a[...][...];")
@@ -935,6 +947,27 @@
     assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
     assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
 
+def test_global_var_array_3():
+    ffi = FFI()
+    ffi.cdef("int a[][...];")
+    lib = verify(ffi, 'test_global_var_array_3', 'int a[10][8];')
+    lib.a[9][7] = 123456
+    assert lib.a[9][7] == 123456
+    py.test.raises(IndexError, 'lib.a[0][8]')
+    assert ffi.typeof(lib.a) == ffi.typeof("int(*)[8]")
+    assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
+
+def test_global_var_array_4():
+    ffi = FFI()
+    ffi.cdef("int a[10][...];")
+    lib = verify(ffi, 'test_global_var_array_4', 'int a[10][8];')
+    lib.a[9][7] = 123456
+    assert lib.a[9][7] == 123456
+    py.test.raises(IndexError, 'lib.a[0][8]')
+    py.test.raises(IndexError, 'lib.a[10][8]')
+    assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
+    assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
+
 def test_some_integer_type():
     ffi = FFI()
     ffi.cdef("""
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to