[pypy-commit] pypy reflex-support: NULL and 0 passing through typed pointers

wlav noreply at buildbot.pypy.org
Fri Jul 20 01:31:30 CEST 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56242:d57f7dde9e95
Date: 2012-07-19 13:49 -0700
http://bitbucket.org/pypy/pypy/changeset/d57f7dde9e95/

Log:	NULL and 0 passing through typed pointers

diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -47,6 +47,24 @@
         return rawobject
     return capi.C_NULL_OBJECT
 
+def get_rawbuffer(space, w_obj):
+    try:
+        buf = space.buffer_w(w_obj)
+        return rffi.cast(rffi.VOIDP, buf.get_raw_address())
+    except Exception:
+        pass
+    # special case: allow integer 0 as NULL
+    try:
+        buf = space.int_w(w_obj)
+        if buf == 0:
+            return rffi.cast(rffi.VOIDP, 0)
+    except Exception:
+        pass
+    # special case: allow None as NULL
+    if space.is_true(space.is_(w_obj, space.w_None)):
+        return rffi.cast(rffi.VOIDP, 0)
+    raise TypeError("not an addressable buffer")
+
 
 class TypeConverter(object):
     _immutable_ = True
@@ -146,16 +164,13 @@
 
     def convert_argument(self, space, w_obj, address, call_local):
         w_tc = space.findattr(w_obj, space.wrap('typecode'))
-        if w_tc is None:
-            raise OperationError(space.w_TypeError, space.wrap("can not determine buffer type"))
-        if space.str_w(w_tc) != self.typecode:
+        if w_tc is not None and space.str_w(w_tc) != self.typecode:
             msg = "expected %s pointer type, but received %s" % (self.typecode, space.str_w(w_tc))
             raise OperationError(space.w_TypeError, space.wrap(msg))
         x = rffi.cast(rffi.LONGP, address)
-        buf = space.buffer_w(w_obj)
         try:
-            x[0] = rffi.cast(rffi.LONG, buf.get_raw_address())
-        except ValueError:
+            x[0] = rffi.cast(rffi.LONG, get_rawbuffer(space, w_obj))
+        except TypeError:
             raise OperationError(space.w_TypeError,
                                  space.wrap("raw buffer interface not supported"))
         ba = rffi.cast(rffi.CCHARP, address)
@@ -351,9 +366,8 @@
         x = rffi.cast(rffi.VOIDPP, address)
         ba = rffi.cast(rffi.CCHARP, address)
         try:
-            buf = space.buffer_w(w_obj)
-            x[0] = rffi.cast(rffi.VOIDP, buf.get_raw_address())
-        except (OperationError, ValueError), e:
+            x[0] = get_rawbuffer(space, w_obj)
+        except TypeError:
             x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         ba[capi.c_function_arg_typeoffset()] = 'o'
 
@@ -369,9 +383,8 @@
         ba = rffi.cast(rffi.CCHARP, address)
         r = rffi.cast(rffi.VOIDPP, call_local)
         try:
-            buf = space.buffer_w(w_obj)
-            r[0] = rffi.cast(rffi.VOIDP, buf.get_raw_address())
-        except (OperationError, ValueError), e:
+            r[0] = get_rawbuffer(space, w_obj)
+        except TypeError:
             r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         x[0] = rffi.cast(rffi.VOIDP, call_local)
         ba[capi.c_function_arg_typeoffset()] = 'a'
@@ -381,7 +394,7 @@
         try:
             set_rawobject(space, w_obj, r[0])
         except OperationError:
-            pass             # no set on buffer/array
+            pass             # no set on buffer/array/None
 
 class VoidPtrRefConverter(TypeConverter):
     _immutable_ = True
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -6,7 +6,7 @@
 from pypy.rlib import libffi, clibffi
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
-from pypy.module._rawffi.array import W_Array
+from pypy.module._rawffi.array import W_Array, W_ArrayInstance
 
 from pypy.module.cppyy import helper, capi, ffitypes
 
@@ -52,6 +52,14 @@
         lresult = capi.c_call_l(cppmethod, cppthis, num_args, args)
         address = rffi.cast(rffi.ULONG, lresult)
         arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap(self.typecode)))
+        if address == 0:
+            # TODO: fix this hack; fromaddress() will allocate memory if address
+            # is null and there seems to be no way around it (ll_buffer can not
+            # be touched directly)
+            nullarr = arr.fromaddress(space, address, 0)
+            assert isinstance(nullarr, W_ArrayInstance)
+            nullarr.free(space)
+            return nullarr
         return arr.fromaddress(space, address, sys.maxint)
 
 
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -387,6 +387,9 @@
         addressofo = array.array('l', [cppyy.addressof(o)])
         assert addressofo.buffer_info()[0] == pp.gime_address_ptr_ptr(addressofo)
 
+        assert 0 == pp.gime_address_ptr(0)
+        assert 0 == pp.gime_address_ptr(None)
+
     def test09_opaque_pointer_assing(self):
         """Test passing around of opaque pointers"""
 
diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py
--- a/pypy/module/cppyy/test/test_datatypes.py
+++ b/pypy/module/cppyy/test/test_datatypes.py
@@ -5,7 +5,7 @@
 currpath = py.path.local(__file__).dirpath()
 test_dct = str(currpath.join("datatypesDict.so"))
 
-space = gettestobjspace(usemodules=['cppyy', 'array'])
+space = gettestobjspace(usemodules=['cppyy', 'array', '_rawffi'])
 
 def setup_module(mod):
     if sys.platform == 'win32':
@@ -226,6 +226,12 @@
             for i in range(self.N):
                 assert ca[i] == b[i]
 
+        # NULL/None passing (will use short*)
+        assert not c.pass_array(0)
+        raises(Exception, c.pass_array(0).__getitem__, 0)    # raises SegfaultException
+        assert not c.pass_array(None)
+        raises(Exception, c.pass_array(None).__getitem__, 0) # id.
+
         c.destruct()
 
     def test05_class_read_access(self):
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -155,10 +155,16 @@
     r_longlong_w = int_w
     r_ulonglong_w = uint_w
 
+    def is_(self, w_obj1, w_obj2):
+        return w_obj1 is w_obj2
+
     def isinstance_w(self, w_obj, w_type):
         assert isinstance(w_obj, FakeBase)
         return w_obj.typename == w_type.name
 
+    def is_true(self, w_obj):
+        return not not w_obj
+
     def type(self, w_obj):
         return FakeType("fake")
 


More information about the pypy-commit mailing list