Author: Wim Lavrijsen <wlavrij...@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] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit