Author: Wim Lavrijsen <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit