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