Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: cppyy-packaging Changeset: r94879:e3fd3632d44e Date: 2018-07-19 10:43 -0700 http://bitbucket.org/pypy/pypy/changeset/e3fd3632d44e/
Log: support for vector<bool> diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py --- a/pypy/module/_cppyy/capi/loadable_capi.py +++ b/pypy/module/_cppyy/capi/loadable_capi.py @@ -274,7 +274,8 @@ 'stdvector_valuetype' : ([c_ccharp], c_ccharp), 'stdvector_valuesize' : ([c_ccharp], c_size_t), - + 'vectorbool_getitem' : ([c_object, c_int], c_int), + 'vectorbool_setitem' : ([c_object, c_int, c_int], c_void), } # size/offset are backend-specific but fixed after load @@ -657,17 +658,43 @@ return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)])) def c_stdvector_valuesize(space, pystr): return _cdata_to_size_t(space, call_capi(space, 'stdvector_valuesize', [_ArgS(pystr)])) +def c_vectorbool_getitem(space, vbool, idx): + return call_capi(space, 'vectorbool_getitem', [_ArgH(vbool), _ArgL(idx)]) +def c_vectorbool_setitem(space, vbool, idx, value): + call_capi(space, 'vectorbool_setitem', [_ArgH(vbool), _ArgL(idx), _ArgL(value)]) # TODO: factor these out ... # pythonizations def stdstring_c_str(space, w_self): """Return a python string taking into account \0""" - from pypy.module._cppyy import interp_cppyy cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False) return space.newtext(c_stdstring2charp(space, cppstr._rawobject)) +def vbool_getindex(space, w_vbool, w_idx): + idx = space.getindex_w(w_idx, space.w_IndexError, "std::vector<bool> index") + sz = space.len_w(w_vbool) + if idx < 0: idx += sz + if idx < 0 or idx >= sz: + raise IndexError + return idx + +def vectorbool_getitem(space, w_self, w_idx): + """Index a std::vector<bool>, return the value""" + from pypy.module._cppyy import interp_cppyy + vbool = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False) + idx = vbool_getindex(space, w_self, w_idx) + item = c_vectorbool_getitem(space, vbool._rawobject, idx) + return space.newbool(space.is_true(item)) + +def vectorbool_setitem(space, w_self, w_idx, w_value): + """Index a std::vector<bool>, set the value""" + from pypy.module._cppyy import interp_cppyy + vbool = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False) + idx = vbool_getindex(space, w_self, w_idx) + c_vectorbool_setitem(space, vbool._rawobject, idx, int(space.is_true(w_value))) + # setup pythonizations for later use at run-time _pythonizations = {} def register_pythonizations(space): @@ -678,6 +705,9 @@ ### std::string stdstring_c_str, + ### std::vector<bool> + vectorbool_getitem, + vectorbool_setitem, ] for f in allfuncs: @@ -692,3 +722,7 @@ space.setattr(w_pycppclass, space.newtext("c_str"), _pythonizations["stdstring_c_str"]) _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str") _method_alias(space, w_pycppclass, "__str__", "c_str") + + if name == "std::vector<bool>": + space.setattr(w_pycppclass, space.newtext("__getitem__"), _pythonizations["vectorbool_getitem"]) + space.setattr(w_pycppclass, space.newtext("__setitem__"), _pythonizations["vectorbool_setitem"]) diff --git a/pypy/module/_cppyy/include/capi.h b/pypy/module/_cppyy/include/capi.h --- a/pypy/module/_cppyy/include/capi.h +++ b/pypy/module/_cppyy/include/capi.h @@ -219,6 +219,10 @@ const char* cppyy_stdvector_valuetype(const char* clname); RPY_EXTERN size_t cppyy_stdvector_valuesize(const char* clname); + RPY_EXTERN + int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx); + RPY_EXTERN + void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value); #ifdef __cplusplus } diff --git a/pypy/module/_cppyy/pythonify.py b/pypy/module/_cppyy/pythonify.py --- a/pypy/module/_cppyy/pythonify.py +++ b/pypy/module/_cppyy/pythonify.py @@ -431,18 +431,19 @@ # not on vector, which is pythonized in the capi (interp-level; there is # also the fallback on the indexed __getitem__, but that is slower) # TODO: if not (0 <= name.find('vector') <= 5): - if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__): - if _cppyy._scope_byname(name+'::iterator') or \ - _cppyy._scope_byname(name+'::const_iterator'): - def __iter__(self): - i = self.begin() - while i != self.end(): - yield i.__deref__() - i.__preinc__() - i.__destruct__() - raise StopIteration - pyclass.__iter__ = __iter__ - # else: rely on numbered iteration + if not (0 <= name.find('vector<bool') <= 5): + if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__): + if _cppyy._scope_byname(name+'::iterator') or \ + _cppyy._scope_byname(name+'::const_iterator'): + def __iter__(self): + i = self.begin() + while i != self.end(): + yield i.__deref__() + i.__preinc__() + i.__destruct__() + raise StopIteration + pyclass.__iter__ = __iter__ + # else: rely on numbered iteration # add python collection based initializer if 0 <= name.find('vector') <= 5: diff --git a/pypy/module/_cppyy/test/test_stltypes.py b/pypy/module/_cppyy/test/test_stltypes.py --- a/pypy/module/_cppyy/test/test_stltypes.py +++ b/pypy/module/_cppyy/test/test_stltypes.py @@ -197,6 +197,26 @@ assert v2[-1] == v[-2] assert v2[self.N-4] == v[-2] + def test07_vector_bool(self): + """Usability of std::vector<bool> which can be a specialization""" + + import _cppyy as cppyy + + vb = cppyy.gbl.std.vector(bool)(8) + assert [x for x in vb] == [False]*8 + + vb[0] = True + assert vb[0] + vb[-1] = True + assert vb[7] + + print [x for x in vb] + + assert [x for x in vb] == [True]+[False]*6+[True] + + assert len(vb[4:8]) == 4 + assert list(vb[4:8]) == [False]*3+[True] + class AppTestSTLSTRING: spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools']) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit