[pypy-commit] pypy reflex-support: allow int(0) and None to be passed as NULL through instance*

wlav noreply at buildbot.pypy.org
Wed Sep 11 01:31:14 CEST 2013


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r66897:51089b1669b5
Date: 2013-09-10 15:55 -0700
http://bitbucket.org/pypy/pypy/changeset/51089b1669b5/

Log:	allow int(0) and None to be passed as NULL through instance*

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,21 +47,22 @@
         return rawobject
     return capi.C_NULL_OBJECT
 
+def is_nullpointer_specialcase(space, w_obj):
+    # special case: allow integer 0 as (void*)0
+    try:
+        return space.int_w(w_obj) == 0
+    except Exception:
+        pass
+    # special case: allow None as (void*)0
+    return space.is_true(space.is_(w_obj, space.w_None))
+
 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)):
+    if is_nullpointer_specialcase(space, w_obj):
         return rffi.cast(rffi.VOIDP, 0)
     raise TypeError("not an addressable buffer")
 
@@ -412,7 +413,7 @@
     _immutable_fields_ = ['uses_local']
     uses_local = True
 
-class InstancePtrConverter(TypeConverter):
+class InstanceRefConverter(TypeConverter):
     _immutable_fields_ = ['libffitype', 'cppclass']
 
     libffitype  = jit_libffi.types.pointer
@@ -444,17 +445,7 @@
         x = rffi.cast(rffi.VOIDPP, address)
         x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
 
-    def from_memory(self, space, w_obj, w_pycppclass, offset):
-        address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
-        from pypy.module.cppyy import interp_cppyy
-        return interp_cppyy.wrap_cppobject(space, address, self.cppclass,
-                                           do_cast=False, is_ref=True)
-
-    def to_memory(self, space, w_obj, w_value, offset):
-        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
-        address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
-
-class InstanceConverter(InstancePtrConverter):
+class InstanceConverter(InstanceRefConverter):
 
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
@@ -468,6 +459,28 @@
     def to_memory(self, space, w_obj, w_value, offset):
         self._is_abstract(space)
 
+
+class InstancePtrConverter(InstanceRefConverter):
+
+    def _unwrap_object(self, space, w_obj):
+        try:
+            return InstanceRefConverter._unwrap_object(self, space, w_obj)
+        except OperationError, e:
+            # if not instance, allow certain special cases
+            if is_nullpointer_specialcase(space, w_obj):
+                return capi.C_NULL_OBJECT
+            raise e
+
+    def from_memory(self, space, w_obj, w_pycppclass, offset):
+        address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
+        from pypy.module.cppyy import interp_cppyy
+        return interp_cppyy.wrap_cppobject(space, address, self.cppclass,
+                                           do_cast=False, is_ref=True)
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
+        address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
+
 class InstancePtrPtrConverter(InstancePtrConverter):
     _immutable_fields_ = ['uses_local']
 
@@ -487,12 +500,6 @@
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
-    def from_memory(self, space, w_obj, w_pycppclass, offset):
-        self._is_abstract(space)
-
-    def to_memory(self, space, w_obj, w_value, offset):
-        self._is_abstract(space)
-
     def finalize_call(self, space, w_obj, call_local):
         from pypy.module.cppyy.interp_cppyy import W_CPPInstance
         assert isinstance(w_obj, W_CPPInstance)
@@ -628,8 +635,10 @@
         # type check for the benefit of the annotator
         from pypy.module.cppyy.interp_cppyy import W_CPPClass
         cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
-        if compound == "*" or compound == "&":
+        if compound == "*":
             return InstancePtrConverter(space, cppclass)
+        elif compound == "&":
+            return InstanceRefConverter(space, cppclass)
         elif compound == "**":
             return InstancePtrPtrConverter(space, cppclass)
         elif compound == "":
diff --git a/pypy/module/cppyy/test/datatypes.cxx b/pypy/module/cppyy/test/datatypes.cxx
--- a/pypy/module/cppyy/test/datatypes.cxx
+++ b/pypy/module/cppyy/test/datatypes.cxx
@@ -119,10 +119,12 @@
 double* cppyy_test_data::get_double_array2() { return m_double_array2; }
 
 cppyy_test_pod cppyy_test_data::get_pod_val() { return m_pod; }
-cppyy_test_pod* cppyy_test_data::get_pod_ptr() { return &m_pod; }
-cppyy_test_pod& cppyy_test_data::get_pod_ref() { return m_pod; }
+cppyy_test_pod* cppyy_test_data::get_pod_val_ptr() { return &m_pod; }
+cppyy_test_pod& cppyy_test_data::get_pod_val_ref() { return m_pod; }
 cppyy_test_pod*& cppyy_test_data::get_pod_ptrref() { return m_ppod; }
 
+cppyy_test_pod* cppyy_test_data::get_pod_ptr() { return m_ppod; }
+
 //- setters -----------------------------------------------------------------
 void cppyy_test_data::set_bool(bool b)                       { m_bool   = b; }
 void cppyy_test_data::set_char(char c)                       { m_char   = c; }
@@ -159,6 +161,8 @@
 void cppyy_test_data::set_pod_void_ptrptr_out(void** pp)       { delete *((cppyy_test_pod**)pp);
                                                                  *((cppyy_test_pod**)pp) = new cppyy_test_pod(m_pod); }
 
+void cppyy_test_data::set_pod_ptr(cppyy_test_pod* pp)          { m_ppod = pp; }
+
 //- passers -----------------------------------------------------------------
 short*          cppyy_test_data::pass_array(short* a)          { return a; }
 unsigned short* cppyy_test_data::pass_array(unsigned short* a) { return a; }
diff --git a/pypy/module/cppyy/test/datatypes.h b/pypy/module/cppyy/test/datatypes.h
--- a/pypy/module/cppyy/test/datatypes.h
+++ b/pypy/module/cppyy/test/datatypes.h
@@ -89,11 +89,13 @@
     double* get_double_array();
     double* get_double_array2();
 
-    cppyy_test_pod get_pod_val();
-    cppyy_test_pod* get_pod_ptr();
-    cppyy_test_pod& get_pod_ref();
+    cppyy_test_pod get_pod_val();                 // for m_pod
+    cppyy_test_pod* get_pod_val_ptr();
+    cppyy_test_pod& get_pod_val_ref();
     cppyy_test_pod*& get_pod_ptrref();
 
+    cppyy_test_pod* get_pod_ptr();                // for m_ppod
+
 // setters
     void set_bool(bool b);
     void set_char(char c);
@@ -120,7 +122,7 @@
     void set_double_c(const double& d);
     void set_enum(what w);
 
-    void set_pod_val(cppyy_test_pod);
+    void set_pod_val(cppyy_test_pod);             // for m_pod
     void set_pod_ptr_in(cppyy_test_pod*);
     void set_pod_ptr_out(cppyy_test_pod*);
     void set_pod_ref(const cppyy_test_pod&);
@@ -129,6 +131,8 @@
     void set_pod_ptrptr_out(cppyy_test_pod**);
     void set_pod_void_ptrptr_out(void**);
 
+    void set_pod_ptr(cppyy_test_pod*);            // for m_ppod
+
 // passers
     short*          pass_array(short*);
     unsigned short* pass_array(unsigned short*);
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
@@ -514,15 +514,15 @@
         assert pod.m_int == 888
         assert pod.m_double == 3.14
 
-        assert c.get_pod_ptr().m_int == 888
-        assert c.get_pod_ptr().m_double == 3.14
-        c.get_pod_ptr().m_int = 777
-        assert c.get_pod_ptr().m_int == 777
+        assert c.get_pod_val_ptr().m_int == 888
+        assert c.get_pod_val_ptr().m_double == 3.14
+        c.get_pod_val_ptr().m_int = 777
+        assert c.get_pod_val_ptr().m_int == 777
 
-        assert c.get_pod_ref().m_int == 777
-        assert c.get_pod_ref().m_double == 3.14
-        c.get_pod_ref().m_int = 666
-        assert c.get_pod_ref().m_int == 666
+        assert c.get_pod_val_ref().m_int == 777
+        assert c.get_pod_val_ref().m_double == 3.14
+        c.get_pod_val_ref().m_int = 666
+        assert c.get_pod_val_ref().m_int == 666
 
         assert c.get_pod_ptrref().m_int == 666
         assert c.get_pod_ptrref().m_double == 3.14
@@ -595,7 +595,22 @@
         assert p.m_int == 888
         assert p.m_double == 3.14
 
-    def test16_respect_privacy(self):
+    def test16_nullptr_passing(self):
+        """Integer 0 ('NULL') and None allowed to pass through instance*"""
+
+        import cppyy
+
+        for o in (0, None):
+            c = cppyy.gbl.cppyy_test_data()
+            assert c.m_pod.m_int == 888
+            assert c.m_pod.m_double == 3.14
+            assert not not c.m_ppod
+
+            c.set_pod_ptr(o)
+            assert not c.m_ppod
+            assert not c.get_pod_ptr()
+
+    def test17_respect_privacy(self):
         """Test that privacy settings are respected"""
 
         import cppyy
@@ -608,7 +623,7 @@
 
         c.destruct()
 
-    def test17_object_and_pointer_comparisons(self):
+    def test18_object_and_pointer_comparisons(self):
         """Verify object and pointer comparisons"""
     
         import cppyy 
@@ -645,7 +660,7 @@
         assert l3 != l5
         assert l5 != l3
 
-    def test18_object_validity(self):
+    def test19_object_validity(self):
         """Test object validity checking"""
         
         from cppyy import gbl
@@ -659,7 +674,7 @@
 
         assert not d2
 
-    def test19_buffer_reshaping(self):
+    def test20_buffer_reshaping(self):
         """Test usage of buffer sizing"""
 
         import cppyy


More information about the pypy-commit mailing list