[pypy-commit] cffi default: Accessing global array variables. C is fun :-/

arigo noreply at buildbot.pypy.org
Fri Jun 15 20:39:45 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r373:96f9a1b9fe69
Date: 2012-06-15 20:39 +0200
http://bitbucket.org/cffi/cffi/changeset/96f9a1b9fe69/

Log:	Accessing global array variables. C is fun :-/

diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -3411,6 +3411,7 @@
     _cffi_restore_errno,
     _cffi_save_errno,
     _cffi_from_c_char,
+    convert_to_object,
 };
 
 /************************************************************/
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -165,6 +165,9 @@
         elif isinstance(tp, model.PointerType):
             return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
                 var, self.gettypenum(tp))
+        elif isinstance(tp, model.ArrayType):
+            return '_cffi_from_c_deref((char *)%s, _cffi_type(%d))' % (
+                var, self.gettypenum(tp))
         else:
             raise NotImplementedError(tp)
 
@@ -351,7 +354,8 @@
     # ----------
     # constants, likely declared with '#define'
 
-    def _generate_cpy_const(self, is_int, name, tp=None, category='const'):
+    def _generate_cpy_const(self, is_int, name, tp=None, category='const',
+                            vartp=None):
         prnt = self.prnt
         funcname = '_cffi_%s_%s' % (category, name)
         prnt('static int %s(PyObject *lib)' % funcname)
@@ -359,7 +363,7 @@
         prnt('  PyObject *o;')
         prnt('  int res;')
         if not is_int:
-            prnt('  %s;' % tp.get_c_name(' i'))
+            prnt('  %s;' % (vartp or tp).get_c_name(' i'))
         else:
             assert category == 'const'
         #
@@ -452,13 +456,19 @@
     # global variables
 
     def generate_cpy_variable_decl(self, tp, name):
-        tp_ptr = model.PointerType(tp)
-        self._generate_cpy_const(False, name, tp_ptr, category='var')
+        if isinstance(tp, model.ArrayType):
+            tp_ptr = model.PointerType(tp.item)
+            self._generate_cpy_const(False, name, tp, vartp=tp_ptr)
+        else:
+            tp_ptr = model.PointerType(tp)
+            self._generate_cpy_const(False, name, tp_ptr, category='var')
 
     generate_cpy_variable_method = generate_nothing
     loading_cpy_variable = loaded_noop
 
     def loaded_cpy_variable(self, tp, name, module, library):
+        if isinstance(tp, model.ArrayType):   # a[5] is "constant" in the
+            return                            # sense that "a=..." is forbidden
         # remove ptr=<cdata 'int *'> from the library instance, and replace
         # it by a property on the class, which reads/writes into ptr[0].
         ptr = getattr(library, name)
@@ -541,7 +551,9 @@
     ((void(*)(void))_cffi_exports[14])
 #define _cffi_from_c_char                                                \
     ((PyObject *(*)(char))_cffi_exports[15])
-#define _CFFI_NUM_EXPORTS 16
+#define _cffi_from_c_deref                                               \
+    ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
+#define _CFFI_NUM_EXPORTS 17
 
 #if SIZEOF_LONG < SIZEOF_LONG_LONG
 #  define _cffi_to_c_long_long PyLong_AsLongLong
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -373,3 +373,20 @@
     lib.somenumber = -6
     assert lib.foo() == -42
     assert lib.somenumber == -6
+
+def test_access_array_variable():
+    ffi = FFI()
+    ffi.cdef("int foo(int);\n"
+             "int somenumber[5];")
+    lib = ffi.verify("""
+        static int somenumber[] = {2, 2, 3, 4, 5};
+        static int foo(int i) {
+            return somenumber[i] * 7;
+        }
+    """)
+    assert lib.somenumber[3] == 4
+    assert lib.foo(3) == 28
+    lib.somenumber[3] = -6
+    assert lib.foo(3) == -42
+    assert lib.somenumber[3] == -6
+    assert lib.somenumber[4] == 5


More information about the pypy-commit mailing list