[pypy-commit] cffi default: Test and fix.

arigo noreply at buildbot.pypy.org
Sat Aug 4 22:03:15 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r781:09102559bc4c
Date: 2012-08-04 22:03 +0200
http://bitbucket.org/cffi/cffi/changeset/09102559bc4c/

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
@@ -585,7 +585,16 @@
                          ct->ct_name);
             return NULL;
         }
-        else if (ct->ct_flags & (CT_ARRAY|CT_STRUCT|CT_UNION)) {
+        else if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
+            return new_simple_cdata(data, ct);
+        }
+        else if (ct->ct_flags & CT_ARRAY) {
+            if (ct->ct_length < 0) {
+                /* we can't return a <cdata 'int[]'> here, because we don't
+                   know the length to give it.  As a compromize, returns
+                   <cdata 'int *'> in this case. */
+                ct = (CTypeDescrObject *)ct->ct_stuff;
+            }
             return new_simple_cdata(data, ct);
         }
     }
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -968,7 +968,10 @@
         return funcobj
 
     def read_variable(self, BType, name):
-        ctypes_obj = BType._ctype.in_dll(self.cdll, name)
+        try:
+            ctypes_obj = BType._ctype.in_dll(self.cdll, name)
+        except AttributeError, e:
+            raise NotImplementedError(e)
         return BType._from_ctypes(ctypes_obj)
 
     def write_variable(self, BType, name, value):
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -396,6 +396,11 @@
                                               # sense that "a=..." is forbidden
             tp_ptr = model.PointerType(tp.item)
             value = self._load_constant(False, tp_ptr, name, module)
+            # 'value' is a <cdata 'type *'> which we have to replace with
+            # a <cdata 'type[N]'> if the N is actually known
+            if tp.length is not None:
+                BArray = self.ffi._get_cached_btype(tp)
+                value = self.ffi.cast(BArray, value)
             setattr(library, name, value)
             return
         # remove ptr=<cdata 'int *'> from the library instance, and replace
diff --git a/testing/test_ownlib.py b/testing/test_ownlib.py
--- a/testing/test_ownlib.py
+++ b/testing/test_ownlib.py
@@ -15,6 +15,8 @@
 int test_setting_errno(void) {
     return errno;
 }
+
+int my_array[7] = {0, 1, 2, 3, 4, 5, 6};
 """
 
 class TestOwnLib(object):
@@ -30,9 +32,11 @@
             cwd=str(udir), shell=True)
         cls.module = str(udir.join('testownlib.so'))
 
-    def test_getting_errno(self):
+    def setup_method(self, meth):
         if sys.platform == 'win32':
             py.test.skip("fix the auto-generation of the tiny test lib")
+
+    def test_getting_errno(self):
         ffi = FFI(backend=self.Backend())
         ffi.cdef("""
             int test_getting_errno(void);
@@ -43,8 +47,6 @@
         assert ffi.errno == 123
 
     def test_setting_errno(self):
-        if sys.platform == 'win32':
-            py.test.skip("fix the auto-generation of the tiny test lib")
         if self.Backend is CTypesBackend and '__pypy__' in sys.modules:
             py.test.skip("XXX errno issue with ctypes on pypy?")
         ffi = FFI(backend=self.Backend())
@@ -56,3 +58,39 @@
         res = ownlib.test_setting_errno()
         assert res == 42
         assert ffi.errno == 42
+
+    def test_my_array_7(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            int my_array[7];
+        """)
+        ownlib = ffi.dlopen(self.module)
+        for i in range(7):
+            assert ownlib.my_array[i] == i
+        assert len(ownlib.my_array) == 7
+        if self.Backend is CTypesBackend:
+            py.test.skip("not supported by the ctypes backend")
+        ownlib.my_array = range(10, 17)
+        for i in range(7):
+            assert ownlib.my_array[i] == 10 + i
+        ownlib.my_array = range(7)
+        for i in range(7):
+            assert ownlib.my_array[i] == i
+
+    def test_my_array_no_length(self):
+        if self.Backend is CTypesBackend:
+            py.test.skip("not supported by the ctypes backend")
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            int my_array[];
+        """)
+        ownlib = ffi.dlopen(self.module)
+        for i in range(7):
+            assert ownlib.my_array[i] == i
+        py.test.raises(TypeError, len, ownlib.my_array)
+        ownlib.my_array = range(10, 17)
+        for i in range(7):
+            assert ownlib.my_array[i] == 10 + i
+        ownlib.my_array = range(7)
+        for i in range(7):
+            assert ownlib.my_array[i] == i
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -426,16 +426,26 @@
     assert lib.somenumber == 42
     lib.somenumber = 2    # reset for the next run, if any
 
-def test_access_array_variable():
+def test_access_array_variable(length=5):
     ffi = FFI()
     ffi.cdef("int foo(int);\n"
-             "int somenumber[5];")
+             "int somenumber[%s];" % (length,))
     lib = ffi.verify("""
         static int somenumber[] = {2, 2, 3, 4, 5};
         static int foo(int i) {
             return somenumber[i] * 7;
         }
     """)
+    if length == '':
+        # a global variable of an unknown array length is implicitly
+        # transformed into a global pointer variable, because we can only
+        # work with array instances whose length we know.  using a pointer
+        # instead of an array gives the correct effects.
+        assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
+        py.test.raises(TypeError, len, lib.somenumber)
+    else:
+        assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
+        assert len(lib.somenumber) == 5
     assert lib.somenumber[3] == 4
     assert lib.foo(3) == 28
     lib.somenumber[3] = -6
@@ -444,6 +454,9 @@
     assert lib.somenumber[4] == 5
     lib.somenumber[3] = 4    # reset for the next run, if any
 
+def test_access_array_variable_length_hidden():
+    test_access_array_variable(length='')
+
 def test_access_struct_variable():
     ffi = FFI()
     ffi.cdef("struct foo { int x; ...; };\n"


More information about the pypy-commit mailing list