[pypy-commit] pypy default: Update to cffi/57afc244cbc2

arigo noreply at buildbot.pypy.org
Mon Jul 6 19:20:39 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r78471:bdc5e9f6119d
Date: 2015-07-06 19:20 +0200
http://bitbucket.org/pypy/pypy/changeset/bdc5e9f6119d/

Log:	Update to cffi/57afc244cbc2

diff --git a/pypy/module/_cffi_backend/cglob.py b/pypy/module/_cffi_backend/cglob.py
--- a/pypy/module/_cffi_backend/cglob.py
+++ b/pypy/module/_cffi_backend/cglob.py
@@ -1,3 +1,4 @@
+from pypy.interpreter.error import oefmt
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.typedef import TypeDef
 from pypy.module._cffi_backend.cdataobj import W_CData
@@ -10,26 +11,34 @@
 class W_GlobSupport(W_Root):
     _immutable_fields_ = ['w_ctype', 'ptr', 'fetch_addr']
 
-    def __init__(self, space, w_ctype, ptr=lltype.nullptr(rffi.CCHARP.TO),
+    def __init__(self, space, name, w_ctype, ptr=lltype.nullptr(rffi.CCHARP.TO),
                  fetch_addr=lltype.nullptr(rffi.VOIDP.TO)):
         self.space = space
+        self.name = name
         self.w_ctype = w_ctype
         self.ptr = ptr
         self.fetch_addr = fetch_addr
 
     def fetch_global_var_addr(self):
         if self.ptr:
-            return self.ptr
-        if not we_are_translated():
-            FNPTR = rffi.CCallback([], rffi.VOIDP)
-            fetch_addr = rffi.cast(FNPTR, self.fetch_addr)
-            result = fetch_addr()
+            result = self.ptr
         else:
-            # careful in translated versions: we need to call fetch_addr,
-            # but in a GIL-releasing way.  The easiest is to invoke a
-            # llexternal() helper.
-            result = pypy__cffi_fetch_var(self.fetch_addr)
-        return rffi.cast(rffi.CCHARP, result)
+            if not we_are_translated():
+                FNPTR = rffi.CCallback([], rffi.VOIDP)
+                fetch_addr = rffi.cast(FNPTR, self.fetch_addr)
+                result = fetch_addr()
+            else:
+                # careful in translated versions: we need to call fetch_addr,
+                # but in a GIL-releasing way.  The easiest is to invoke a
+                # llexternal() helper.
+                result = pypy__cffi_fetch_var(self.fetch_addr)
+            result = rffi.cast(rffi.CCHARP, result)
+        if not result:
+            from pypy.module._cffi_backend import ffi_obj
+            ffierror = ffi_obj.get_ffi_error(self.space)
+            raise oefmt(ffierror, "global variable '%s' is at address NULL",
+                        self.name)
+        return result
 
     def read_global_var(self):
         return self.w_ctype.convert_to_object(self.fetch_global_var_addr())
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -115,12 +115,12 @@
                 ptr = rffi.cast(rffi.CCHARP, g.c_address)
                 if not ptr:   # for dlopen() style
                     ptr = self.cdlopen_fetch(attr)
-                w_result = cglob.W_GlobSupport(space, w_ct, ptr=ptr)
+                w_result = cglob.W_GlobSupport(space, attr, w_ct, ptr=ptr)
                 #
             elif op == cffi_opcode.OP_GLOBAL_VAR_F:
                 w_ct = realize_c_type.realize_c_type(
                     self.ffi, self.ctx.c_types, getarg(g.c_type_op))
-                w_result = cglob.W_GlobSupport(space, w_ct,
+                w_result = cglob.W_GlobSupport(space, attr, w_ct,
                                                fetch_addr=g.c_address)
                 #
             elif (op == cffi_opcode.OP_CONSTANT_INT or
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -1057,3 +1057,22 @@
         assert values[2] == 42
         assert p[-1] == 41
         assert p[+1] == 42
+        #
+        # if get_my_value raises or returns nonsense, the exception is printed
+        # to stderr like with any callback, but then the C expression 'my_value'
+        # expand to '*NULL'.  We assume here that '&my_value' will return NULL
+        # without segfaulting, and check for NULL when accessing the variable.
+        @ffi.callback("int *(*)(void)")
+        def get_my_value():
+            raise LookupError
+        lib.get_my_value = get_my_value
+        raises(ffi.error, getattr, lib, 'my_value')
+        raises(ffi.error, setattr, lib, 'my_value', 50)
+        raises(ffi.error, ffi.addressof, lib, 'my_value')
+        @ffi.callback("int *(*)(void)")
+        def get_my_value():
+            return "hello"
+        lib.get_my_value = get_my_value
+        raises(ffi.error, getattr, lib, 'my_value')
+        e = raises(ffi.error, setattr, lib, 'my_value', 50)
+        assert str(e.value) == "global variable 'my_value' is at address NULL"


More information about the pypy-commit mailing list