Author: Wim Lavrijsen <wlavrij...@lbl.gov>
Branch: reflex-support
Changeset: r53038:239a04b34d26
Date: 2012-02-29 16:44 -0800
http://bitbucket.org/pypy/pypy/changeset/239a04b34d26/

Log:    support for global pointer types

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
@@ -16,8 +16,19 @@
     from pypy.module.cppyy.interp_cppyy import W_CPPInstance
     cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
     if cppinstance:
-        assert lltype.typeOf(cppinstance.rawobject) == capi.C_OBJECT
-        return cppinstance.rawobject
+        rawobject = cppinstance.get_rawobject()
+        assert lltype.typeOf(rawobject) == capi.C_OBJECT
+        return rawobject
+    return capi.C_NULL_OBJECT
+
+def get_rawobject_nonnull(space, w_obj):
+    from pypy.module.cppyy.interp_cppyy import W_CPPInstance
+    cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
+    if cppinstance:
+        cppinstance._nullcheck()
+        rawobject = cppinstance.get_rawobject()
+        assert lltype.typeOf(rawobject) == capi.C_OBJECT
+        return rawobject
     return capi.C_NULL_OBJECT
 
 
@@ -31,7 +42,7 @@
         pass
 
     def _get_raw_address(self, space, w_obj, offset):
-        rawobject = get_rawobject(space, w_obj)
+        rawobject = get_rawobject_nonnull(space, w_obj)
         assert lltype.typeOf(rawobject) == capi.C_OBJECT
         if rawobject:
             fieldptr = capi.direct_ptradd(rawobject, offset)
@@ -123,7 +134,7 @@
 
     def to_memory(self, space, w_obj, w_value, offset):
         # copy only the pointer value
-        rawobject = get_rawobject(space, w_obj)
+        rawobject = get_rawobject_nonnull(space, w_obj)
         byteptr = rffi.cast(rffi.CCHARPP, capi.direct_ptradd(rawobject, 
offset))
         buf = space.buffer_w(w_value)
         try:
@@ -500,9 +511,10 @@
         obj = space.interpclass_w(w_obj)
         if isinstance(obj, W_CPPInstance):
             if capi.c_is_subtype(obj.cppclass.handle, self.cpptype.handle):
+                rawobject = obj.get_rawobject()
                 offset = capi.c_base_offset(
-                    obj.cppclass.handle, self.cpptype.handle, obj.rawobject)
-                obj_address = capi.direct_ptradd(obj.rawobject, offset)
+                    obj.cppclass.handle, self.cpptype.handle, rawobject)
+                obj_address = capi.direct_ptradd(rawobject, offset)
                 return rffi.cast(capi.C_OBJECT, obj_address)
         raise TypeError("cannot pass %s as %s" %
                         (space.type(w_obj).getname(space, "?"), 
self.cpptype.name))
@@ -517,6 +529,14 @@
     def convert_argument_libffi(self, space, w_obj, argchain):
         argchain.arg(self._unwrap_object(space, w_obj))
 
+    def from_memory(self, space, w_obj, w_type, 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.new_instance(space, w_type, self.cpptype, address, 
True, False)
+
+    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):
     _immutable_ = True
@@ -524,7 +544,10 @@
     def from_memory(self, space, w_obj, w_type, 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.new_instance(space, w_type, self.cpptype, address, 
False)
+        return interp_cppyy.new_instance(space, w_type, self.cpptype, address, 
False, False)
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        self._is_abstract(space)
 
 
 class StdStringConverter(InstanceConverter):
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
@@ -248,12 +248,12 @@
         from pypy.module.cppyy import interp_cppyy
         long_result = capi.c_call_l(cppmethod, cppthis, num_args, args)
         ptr_result = rffi.cast(capi.C_OBJECT, long_result)
-        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, False)
+        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, False, False)
 
     def execute_libffi(self, space, w_returntype, libffifunc, argchain):
         from pypy.module.cppyy import interp_cppyy
         ptr_result = rffi.cast(capi.C_OBJECT, libffifunc.call(argchain, 
rffi.VOIDP))
-        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, False)
+        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, False, False)
 
 
 class InstanceExecutor(InstancePtrExecutor):
@@ -263,7 +263,7 @@
         from pypy.module.cppyy import interp_cppyy
         long_result = capi.c_call_o(cppmethod, cppthis, num_args, args, 
self.cpptype.handle)
         ptr_result = rffi.cast(capi.C_OBJECT, long_result)
-        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, True)
+        return interp_cppyy.new_instance(space, w_returntype, self.cpptype, 
ptr_result, False, True)
 
     def execute_libffi(self, space, w_returntype, libffifunc, argchain):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
diff --git a/pypy/module/cppyy/interp_cppyy.py 
b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -225,7 +225,7 @@
         except Exception:
             capi.c_deallocate(self.cpptype.handle, newthis)
             raise
-        return new_instance(self.space, w_type, self.cpptype, newthis, True)
+        return new_instance(self.space, w_type, self.cpptype, newthis, False, 
True)
 
 
 class W_CPPOverload(Wrappable):
@@ -300,7 +300,7 @@
         if cppinstance:
             assert lltype.typeOf(cppinstance.cppclass.handle) == 
lltype.typeOf(self.scope_handle)
             offset = self.offset + capi.c_base_offset(
-                cppinstance.cppclass.handle, self.scope_handle, 
cppinstance.rawobject)
+                cppinstance.cppclass.handle, self.scope_handle, 
cppinstance.get_rawobject())
         else:
             offset = self.offset
         return offset
@@ -310,7 +310,7 @@
         offset = self._get_offset(cppinstance)
         try:
             return self.converter.from_memory(self.space, w_cppinstance, 
w_type, offset)
-        except Exception, e:
+        except TypeError, e:
             raise OperationError(self.space.w_TypeError, 
self.space.wrap(str(e)))
         except ValueError, e:
             raise OperationError(self.space.w_ValueError, 
self.space.wrap(str(e)))
@@ -490,7 +490,7 @@
 
     def get_cppthis(self, cppinstance, scope_handle):
         assert self.handle == cppinstance.cppclass.handle
-        return cppinstance.rawobject
+        return cppinstance.get_rawobject()
 
     def is_namespace(self):
         return self.space.w_False
@@ -521,8 +521,8 @@
 
     def get_cppthis(self, cppinstance, scope_handle):
         assert self.handle == cppinstance.cppclass.handle
-        offset = capi.c_base_offset(self.handle, scope_handle, 
cppinstance.rawobject)
-        return capi.direct_ptradd(cppinstance.rawobject, offset)
+        offset = capi.c_base_offset(self.handle, scope_handle, 
cppinstance.get_rawobject())
+        return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
 
 W_ComplexCPPType.typedef = TypeDef(
     'ComplexCPPType',
@@ -559,24 +559,34 @@
 
 
 class W_CPPInstance(Wrappable):
-    _immutable_fields_ = ["cppclass"]
+    _immutable_fields_ = ["cppclass", "isref"]
 
-    def __init__(self, space, cppclass, rawobject, python_owns):
+    def __init__(self, space, cppclass, rawobject, isref, python_owns):
         self.space = space
         assert isinstance(cppclass, W_CPPType)
         self.cppclass = cppclass
         assert lltype.typeOf(rawobject) == capi.C_OBJECT
-        self.rawobject = rawobject
+        assert not isref or rawobject
+        self._rawobject = rawobject
+        assert not isref or not python_owns
+        self.isref = isref
         self.python_owns = python_owns
 
     def _nullcheck(self):
-        if not self.rawobject:
+        if not self._rawobject or (self.isref and not self.get_rawobject()):
             raise OperationError(self.space.w_ReferenceError,
                                  self.space.wrap("trying to access a NULL 
pointer"))
 
+    def get_rawobject(self):
+        if not self.isref:
+            return self._rawobject
+        else:
+            ptrptr = rffi.cast(rffi.VOIDPP, self._rawobject)
+            return rffi.cast(capi.C_OBJECT, ptrptr[0])
+
     def instance__eq__(self, w_other):
         other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
-        iseq = self.rawobject == other.rawobject
+        iseq = self._rawobject == other._rawobject
         return self.space.wrap(iseq)
 
     def instance__ne__(self, w_other):
@@ -584,17 +594,16 @@
 
     def destruct(self):
         assert isinstance(self, W_CPPInstance)
-        if self.rawobject:
+        if self._rawobject and not self.isref:
             memory_regulator.unregister(self)
-            capi.c_destruct(self.cppclass.handle, self.rawobject)
-            self.rawobject = capi.C_NULL_OBJECT
+            capi.c_destruct(self.cppclass.handle, self._rawobject)
+            self._rawobject = capi.C_NULL_OBJECT
 
     def __del__(self):
         if self.python_owns:
             self.enqueue_for_destruction(self.space, W_CPPInstance.destruct,
                                          '__del__() method of ')
 
-
 W_CPPInstance.typedef = TypeDef(
     'CPPInstance',
     cppclass = interp_attrproperty('cppclass', cls=W_CPPInstance),
@@ -617,11 +626,11 @@
         self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
 
     def register(self, obj):
-        int_address = int(rffi.cast(rffi.LONG, obj.rawobject))
+        int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
         self.objects.set(int_address, obj)
 
     def unregister(self, obj):
-        int_address = int(rffi.cast(rffi.LONG, obj.rawobject))
+        int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
         self.objects.set(int_address, None)
 
     def retrieve(self, address):
@@ -631,19 +640,19 @@
 memory_regulator = MemoryRegulator()
 
 
-def new_instance(space, w_type, cpptype, rawobject, python_owns):
+def new_instance(space, w_type, cpptype, rawobject, isref, python_owns):
     obj = memory_regulator.retrieve(rawobject)
     if obj and obj.cppclass == cpptype:
         return obj
     w_cppinstance = space.allocate_instance(W_CPPInstance, w_type)
     cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=False)
-    W_CPPInstance.__init__(cppinstance, space, cpptype, rawobject, python_owns)
+    W_CPPInstance.__init__(cppinstance, space, cpptype, rawobject, isref, 
python_owns)
     memory_regulator.register(cppinstance)
     return w_cppinstance
 
 @unwrap_spec(cppinstance=W_CPPInstance)
 def addressof(space, cppinstance):
-     address = rffi.cast(rffi.LONG, cppinstance.rawobject)
+     address = rffi.cast(rffi.LONG, cppinstance.get_rawobject())
      return space.wrap(address)
 
 @unwrap_spec(address=int, owns=bool)
@@ -656,4 +665,4 @@
     if obj and obj.cppclass == cpptype:
         return obj
 
-    return new_instance(space, w_type, cpptype, rawobject, owns)
+    return new_instance(space, w_type, cpptype, rawobject, False, owns)
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
@@ -339,8 +339,6 @@
         import cppyy
         gbl = cppyy.gbl
 
-        import pprint
-        pprint.pprint(dir(gbl))
         assert gbl.g_int == gbl.get_global_int()
 
         gbl.set_global_int(32)
@@ -350,3 +348,34 @@
         gbl.g_int = 22
         assert gbl.get_global_int() == 22
         assert gbl.g_int == 22
+
+    def test10_global_ptr(self):
+        """Test access of global objects through a pointer"""
+
+        import cppyy
+        gbl = cppyy.gbl
+
+        raises(ReferenceError, 'gbl.g_pod.m_int')
+
+        c = gbl.cppyy_test_pod()
+        c.m_int = 42
+        c.m_double = 3.14
+
+        gbl.set_global_pod(c)
+        assert gbl.is_global_pod(c)
+        assert gbl.g_pod.m_int == 42
+        assert gbl.g_pod.m_double == 3.14
+
+        d = gbl.get_global_pod()
+        assert gbl.is_global_pod(d)
+        assert c == d
+        assert id(c) == id(d)
+
+        e = gbl.cppyy_test_pod()
+        e.m_int = 43
+        e.m_double = 2.14
+
+        gbl.g_pod = e
+        assert gbl.is_global_pod(e)
+        assert gbl.g_pod.m_int == 43
+        assert gbl.g_pod.m_double == 2.14
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to