[pypy-commit] pypy cppyy-packaging: support for vector<bool>

wlav pypy.commits at gmail.com
Thu Jul 19 14:04:07 EDT 2018


Author: Wim Lavrijsen <WLavrijsen at 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'])


More information about the pypy-commit mailing list