[pypy-commit] pypy cppyy-packaging: converter for builtin arrays of instances
wlav
pypy.commits at gmail.com
Thu Jul 19 00:42:43 EDT 2018
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: cppyy-packaging
Changeset: r94878:046b87bc288f
Date: 2018-07-18 21:21 -0700
http://bitbucket.org/pypy/pypy/changeset/046b87bc288f/
Log: converter for builtin arrays of instances
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
@@ -622,6 +622,24 @@
lltype.free(self.ref_buffer, flavor='raw')
self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
+class InstanceArrayConverter(InstancePtrConverter):
+ _immutable_fields_ = ['size']
+
+ def __init__(self, space, clsdecl, array_size):
+ InstancePtrConverter.__init__(self, space, clsdecl)
+ if array_size <= 0:
+ self.size = sys.maxint
+ else:
+ self.size = array_size
+
+ def from_memory(self, space, w_obj, offset):
+ address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
+ return lowlevelviews.W_ArrayOfInstances(space, self.clsdecl, address, self.size)
+
+ def to_memory(self, space, w_obj, w_value, offset):
+ self._is_abstract(space)
+
+
class StdStringConverter(InstanceConverter):
def __init__(self, space, extra):
from pypy.module._cppyy import interp_cppyy
@@ -846,20 +864,19 @@
pass
# match of decorated, unqualified type
- compound = helper.compound(name)
+ cpd = helper.compound(name)
clean_name = capi.c_resolve_name(space, helper.clean_type(name))
try:
- return _converters[clean_name+compound](space, default)
+ return _converters[clean_name+cpd](space, default)
except KeyError:
pass
- # arrays
+ # arrays (array_size may be negative, meaning: no size or no size found)
+ array_size = helper.array_size(_name) # uses original arg
try:
- # array_index may be negative to indicate no size or no size found
- array_size = helper.array_size(_name) # uses original arg
# TODO: using clean_name here drops const (e.g. const char[] will
# never be seen this way)
- return _a_converters[clean_name+compound](space, array_size)
+ return _a_converters[clean_name+cpd](space, array_size)
except KeyError:
pass
@@ -873,24 +890,27 @@
# check smart pointer type
check_smart = capi.c_smartptr_info(space, clean_name)
if check_smart[0]:
- if compound == '':
+ if cpd == '':
return SmartPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
- elif compound == '*':
+ elif cpd == '*':
return SmartPtrPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
- elif compound == '&':
+ elif cpd == '&':
return SmartPtrRefConverter(space, clsdecl, check_smart[1], check_smart[2])
# fall through: can still return smart pointer in non-smart way
# type check for the benefit of the annotator
- if compound == "*":
+ if cpd == "*":
return InstancePtrConverter(space, clsdecl)
- elif compound == "&":
+ elif cpd == "&":
return InstanceRefConverter(space, clsdecl)
- elif compound == "&&":
+ elif cpd == "&&":
return InstanceMoveConverter(space, clsdecl)
- elif compound == "**":
+ elif cpd in ["**", "*[]", "&*"]:
return InstancePtrPtrConverter(space, clsdecl)
- elif compound == "":
+ elif cpd == "[]" and array_size > 0:
+ # TODO: retrieve dimensions
+ return InstanceArrayConverter(space, clsdecl, array_size)
+ elif cpd == "":
return InstanceConverter(space, clsdecl)
elif "(anonymous)" in name:
# special case: enum w/o a type name
@@ -902,7 +922,7 @@
return FunctionPointerConverter(space, name[pos+2:])
# void* or void converter (which fails on use)
- if 0 <= compound.find('*'):
+ if 0 <= cpd.find('*'):
return VoidPtrConverter(space, default) # "user knows best"
# return a void converter here, so that the class can be build even
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
@@ -1040,7 +1040,7 @@
self.space = space
self.scope = decl_scope
self.converter = converter.get_converter(self.space, type_name, '')
- self.offset = offset
+ self.offset = rffi.cast(rffi.LONG, offset)
def _get_offset(self, cppinstance):
if cppinstance:
diff --git a/pypy/module/_cppyy/lowlevelviews.py b/pypy/module/_cppyy/lowlevelviews.py
--- a/pypy/module/_cppyy/lowlevelviews.py
+++ b/pypy/module/_cppyy/lowlevelviews.py
@@ -3,10 +3,16 @@
# a few more methods allowing such information to be set. Afterwards, it is
# simple to pass these views on to e.g. numpy (w/o the need to copy).
-from pypy.interpreter.error import oefmt
+from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty_w
+from pypy.interpreter.baseobjspace import W_Root
+
+from rpython.rtyper.lltypesystem import rffi
+
from pypy.module._rawffi.array import W_ArrayInstance
+from pypy.module._rawffi.interp_rawffi import segfault_exception
+from pypy.module._cppyy import capi
class W_LowLevelView(W_ArrayInstance):
@@ -52,3 +58,33 @@
)
W_ArrayInstance.typedef.acceptable_as_base_class = False
+
+class W_ArrayOfInstances(W_Root):
+ _attrs_ = ['converter', 'baseaddress', 'clssize', 'length']
+ _immutable_fields_ = ['converter', 'baseaddress', 'clssize']
+
+ def __init__(self, space, clsdecl, address, length):
+ from pypy.module._cppyy import converter
+ self.converter = converter.get_converter(space, clsdecl.name, '')
+ self.baseaddress = address
+ self.clssize = capi.c_size_of_klass(space, clsdecl)
+ self.length = length
+
+ @unwrap_spec(idx=int)
+ def getitem(self, space, idx):
+ if not self.baseaddress:
+ raise segfault_exception(space, "accessing elements of freed array")
+ if idx >= self.length or idx < 0:
+ raise OperationError(space.w_IndexError, space.w_None)
+ itemaddress = rffi.cast(rffi.LONG, self.baseaddress+idx*self.clssize)
+ return self.converter.from_memory(space, space.w_None, itemaddress)
+
+ def getlength(self, space):
+ return space.newint(self.length)
+
+W_ArrayOfInstances.typedef = TypeDef(
+ 'ArrayOfInstances',
+ __getitem__ = interp2app(W_ArrayOfInstances.getitem),
+ __len__ = interp2app(W_ArrayOfInstances.getlength),
+)
+W_ArrayOfInstances.typedef.acceptable_as_base_class = False
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
@@ -690,7 +690,6 @@
# TODO: currently fails b/c double** not understood as &double*
#assert cppyy.gbl.my_global_ptr[0] == 1234.
- return
v = cppyy.gbl.my_global_int_holders
assert len(v) == 5
expected_vals = [13, 42, 88, -1, 17]
More information about the pypy-commit
mailing list