[pypy-commit] pypy default: std::vector performance and handle long double through narrowing

wlav pypy.commits at gmail.com
Sat Aug 4 00:10:01 EDT 2018


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: 
Changeset: r94934:cc09dd3d75c4
Date: 2018-08-03 17:44 -0700
http://bitbucket.org/pypy/pypy/changeset/cc09dd3d75c4/

Log:	std::vector performance and handle long double through narrowing

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -8,7 +8,7 @@
 .. branch: cppyy-packaging
 
 Main items: vastly better template resolution and improved performance. In
-detail: upgrade to backend 1.3.1, improved handling of templated methods and
+detail: upgrade to backend 1.4, improved handling of templated methods and
 functions (in particular automatic deduction of types), improved pythonization
 interface, range of compatibility fixes for Python3, free functions now take
 fast libffi path when possible, moves for strings (incl. from Python str),
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
@@ -1,13 +1,18 @@
 import os
+
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel
 from rpython.rlib.rarithmetic import r_singlefloat
 from rpython.tool import leakfinder
 
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import oefmt
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.argument import Arguments
+from pypy.interpreter.gateway import interp2app, interpindirect2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
 
+from pypy.module._rawffi.array import W_ArrayInstance
 from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
 from pypy.module._cffi_backend import newtype
 from pypy.module._cppyy import ffitypes
@@ -23,10 +28,11 @@
 
 class _Arg:         # poor man's union
     _immutable_ = True
-    def __init__(self, tc, h = 0, l = -1, s = '', p = rffi.cast(rffi.VOIDP, 0)):
+    def __init__(self, tc, h = 0, l = -1, d = -1., s = '', p = rffi.cast(rffi.VOIDP, 0)):
         self.tc      = tc
         self._handle = h
         self._long   = l
+        self._double = d
         self._string = s
         self._voidp  = p
 
@@ -40,6 +46,11 @@
     def __init__(self, val):
         _Arg.__init__(self, 'l', l = val)
 
+class _ArgD(_Arg):
+    _immutable_ = True
+    def __init__(self, val):
+        _Arg.__init__(self, 'd', d = val)
+
 class _ArgS(_Arg):
     _immutable_ = True
     def __init__(self, val):
@@ -89,6 +100,9 @@
                     assert obj._voidp != rffi.cast(rffi.VOIDP, 0)
                     data = rffi.cast(rffi.VOIDPP, data)
                     data[0] = obj._voidp
+                elif obj.tc == 'd':
+                    assert isinstance(argtype, ctypeprim.W_CTypePrimitiveFloat)
+                    misc.write_raw_float_data(data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size)
                 else:    # only other use is string
                     assert obj.tc == 's'
                     n = len(obj._string)
@@ -182,6 +196,7 @@
             'call_f'       : ([c_method, c_object, c_int, c_voidp],   c_float),
             'call_d'       : ([c_method, c_object, c_int, c_voidp],   c_double),
             'call_ld'      : ([c_method, c_object, c_int, c_voidp],   c_ldouble),
+            'call_nld'     : ([c_method, c_object, c_int, c_voidp],   c_double),
 
             'call_r'       : ([c_method, c_object, c_int, c_voidp],   c_voidp),
             # call_s actually takes an size_t* as last parameter, but this will do
@@ -274,8 +289,9 @@
             'stdstring2charp'          : ([c_object, c_voidp],        c_ccharp),
             'stdstring2stdstring'      : ([c_object],                 c_object),
 
-            'stdvector_valuetype'      : ([c_ccharp],                 c_ccharp),
-            'stdvector_valuesize'      : ([c_ccharp],                 c_size_t),
+            'longdouble2double'        : ([c_voidp],                  c_double),
+            'double2longdouble'        : ([c_double, c_voidp],        c_void),
+
             'vectorbool_getitem'       : ([c_object, c_int],          c_int),
             'vectorbool_setitem'       : ([c_object, c_int, c_int],   c_void),
         }
@@ -404,7 +420,9 @@
     return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args)))
 def c_call_ld(space, cppmethod, cppobject, nargs, cargs):
     args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
-    return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
+    #return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
+    # call_nld narrows long double to double
+    return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_nld', args)))
 
 def c_call_r(space, cppmethod, cppobject, nargs, cargs):
     args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
@@ -658,13 +676,11 @@
 def c_stdstring2stdstring(space, cppobject):
     return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgH(cppobject)]))
 
-def c_stdvector_valuetype(space, pystr):
-    return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
+def c_longdouble2double(space, addr):
+    return space.float_w(call_capi(space, 'longdouble2double', [_ArgP(addr)]))
+def c_double2longdouble(space, dval, addr):
+    call_capi(space, 'double2longdouble', [_ArgD(dval), _ArgP(addr)])
 
-def c_stdvector_valuetype(space, pystr):
-    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):
@@ -702,6 +718,52 @@
     idx = vbool_getindex(space, w_self, w_idx)
     c_vectorbool_setitem(space, vbool._rawobject, idx, int(space.is_true(w_value)))
 
+class W_STLVectorIter(W_AbstractSeqIterObject):
+    # w_seq and index are in base class
+    _immutable_fields_ = ['converter', 'data', 'len', 'stride']
+
+    def __init__(self, space, w_vector):
+        W_AbstractSeqIterObject.__init__(self, w_vector)
+        # TODO: this should live in rpythonize.py or something so that the
+        # imports can move to the top w/o getting circles
+        from pypy.module._cppyy import interp_cppyy
+        assert isinstance(w_vector, interp_cppyy.W_CPPInstance)
+        vector = space.interp_w(interp_cppyy.W_CPPInstance, w_vector)
+
+        v_type = c_resolve_name(space, vector.clsdecl.name+'::value_type')
+        v_size = c_size_of_type(space, v_type)
+
+        if not v_type or not v_size:
+            raise NotImplementedError   # fallback on getitem
+
+        from pypy.module._cppyy import converter
+        self.converter = converter.get_converter(space, v_type, '')
+
+        # this 'data' is from the decl, so not the pythonized data from pythonify.py
+        w_arr = space.call_obj_args(vector.clsdecl.get_overload('data'), w_vector, Arguments(space, []))
+        arr = space.interp_w(W_ArrayInstance, w_arr, can_be_None=True)
+        if not arr:
+            raise OperationError(space.w_StopIteration, space.w_None)
+
+        self.data    = rffi.cast(rffi.CCHARP, space.uint_w(arr.getbuffer(space)))
+        self.len     = space.uint_w(space.call_obj_args(vector.clsdecl.get_overload('size'), w_vector, Arguments(space, [])))
+        self.stride  = v_size
+
+    def descr_next(self, space):
+        if self.w_seq is None:
+            raise OperationError(space.w_StopIteration, space.w_None)
+        if self.len <= self.index:
+            self.w_seq = None
+            raise OperationError(space.w_StopIteration, space.w_None)
+        offset = lltype.direct_ptradd(self.data, rffi.cast(rffi.SIZE_T, self.index*self.stride))
+        w_item = self.converter.from_memory(space, space.w_None, rffi.cast(rffi.LONG, offset))
+        self.index += 1
+        return w_item
+
+def stdvector_iter(space, w_self):
+    return W_STLVectorIter(space, w_self)
+
+
 # setup pythonizations for later use at run-time
 _pythonizations = {}
 def register_pythonizations(space):
@@ -712,6 +774,9 @@
         ### std::string
         stdstring_c_str,
 
+        ### std::vector
+        stdvector_iter,
+
         ### std::vector<bool>
         vectorbool_getitem,
         vectorbool_setitem,
@@ -730,6 +795,9 @@
         _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str")
         _method_alias(space, w_pycppclass, "__str__",           "c_str")
 
-    if name == "std::vector<bool>":
+    if  name.find("std::vector<bool", 0, 16) == 0:
         space.setattr(w_pycppclass, space.newtext("__getitem__"), _pythonizations["vectorbool_getitem"])
         space.setattr(w_pycppclass, space.newtext("__setitem__"), _pythonizations["vectorbool_setitem"])
+
+    elif name.find("std::vector", 0, 11) == 0:
+        space.setattr(w_pycppclass, space.newtext("__iter__"), _pythonizations["stdvector_iter"])
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
@@ -211,6 +211,9 @@
         x[0] = self._unwrap_object(space, w_obj)
 
     def default_argument_libffi(self, space, address):
+        if not self.valid_default:
+            from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
+            raise FastCallNotPossible
         x = rffi.cast(self.c_ptrtype, address)
         x[0] = self.default
 
@@ -224,7 +227,7 @@
         rffiptr = rffi.cast(self.c_ptrtype, address)
         rffiptr[0] = self._unwrap_object(space, w_value)
 
-class ConstRefNumericTypeConverterMixin(NumericTypeConverterMixin):
+class ConstRefNumericTypeConverterMixin(object):
     _mixin_ = True
 
     def cffi_type(self, space):
@@ -321,59 +324,92 @@
     pass
 
 class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
-    _immutable_fields_ = ['default']
+    _immutable_fields_ = ['default', 'valid_default']
 
     def __init__(self, space, default):
-        if default:
+        self.valid_default = False
+        try:
             fval = float(rfloat.rstring_to_float(default))
-        else:
+            self.valid_default = True
+        except Exception:
             fval = float(0.)
-        self.default = r_singlefloat(fval)
+        self.default = rffi.cast(rffi.FLOAT, r_singlefloat(fval))
 
     def from_memory(self, space, w_obj, offset):
         address = self._get_raw_address(space, w_obj, offset)
         rffiptr = rffi.cast(self.c_ptrtype, address)
         return self._wrap_object(space, rffiptr[0])
 
-class ConstFloatRefConverter(FloatConverter):
+class ConstFloatRefConverter(ConstRefNumericTypeConverterMixin, FloatConverter):
     _immutable_fields_ = ['typecode']
     typecode = 'f'
 
-    def cffi_type(self, space):
-        state = space.fromcache(ffitypes.State)
-        return state.c_voidp
-
-    def convert_argument_libffi(self, space, w_obj, address, scratch):
-        from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
-        raise FastCallNotPossible
-
 class DoubleConverter(ffitypes.typeid(rffi.DOUBLE), FloatTypeConverterMixin, TypeConverter):
-    _immutable_fields_ = ['default']
+    _immutable_fields_ = ['default', 'valid_default']
 
     def __init__(self, space, default):
-        if default:
+        self.valid_default = False
+        try:
             self.default = rffi.cast(self.c_type, rfloat.rstring_to_float(default))
-        else:
+            self.valid_default = True
+        except Exception:
             self.default = rffi.cast(self.c_type, 0.)
 
 class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
     _immutable_fields_ = ['typecode']
     typecode = 'd'
 
-class LongDoubleConverter(ffitypes.typeid(rffi.LONGDOUBLE), FloatTypeConverterMixin, TypeConverter):
-    _immutable_fields_ = ['default']
+class LongDoubleConverter(TypeConverter):
+    _immutable_fields_ = ['default', 'valid_default']
+    typecode = 'g'
 
     def __init__(self, space, default):
-        if default:
-            fval = float(rfloat.rstring_to_float(default))
-        else:
-            fval = float(0.)
-        self.default = r_longfloat(fval)
+        self.valid_default = False
+        try:
+            # use float() instead of cast with r_longfloat
+            fval = rffi.cast(rffi.DOUBLE, rfloat.rstring_to_float(default))
+            self.valid_default = True
+        except Exception:
+            fval = rffi.cast(rffi.DOUBLE, 0.)
+        #self.default = r_longfloat(fval)
+        self.default = fval
+
+    def convert_argument(self, space, w_obj, address):
+        x = rffi.cast(rffi.VOIDP, address)
+        capi.c_double2longdouble(space, space.float_w(w_obj), x)
+        ba = rffi.cast(rffi.CCHARP, address)
+        ba[capi.c_function_arg_typeoffset(space)] = self.typecode
+
+    def convert_argument_libffi(self, space, w_obj, address, scratch):
+        x = rffi.cast(rffi.VOIDP, address)
+        capi.c_double2longdouble(space, space.float_w(w_obj), x)
+
+    def default_argument_libffi(self, space, address):
+        if not self.valid_default:
+            from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
+            raise FastCallNotPossible
+        x = rffi.cast(rffi.VOIDP, address)
+        capi.c_double2longdouble(space, self.default, x)
+
+    def from_memory(self, space, w_obj, offset):
+        address = self._get_raw_address(space, w_obj, offset)
+        rffiptr = rffi.cast(rffi.VOIDP, address)
+        return space.newfloat(capi.c_longdouble2double(space, rffiptr))
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        address = self._get_raw_address(space, w_obj, offset)
+        rffiptr = rffi.cast(rffi.VOIDP, address)
+        capi.c_double2longdouble(space, space.float_w(w_value), rffiptr)
 
 class ConstLongDoubleRefConverter(ConstRefNumericTypeConverterMixin, LongDoubleConverter):
     _immutable_fields_ = ['typecode']
     typecode = 'g'
 
+    def convert_argument_libffi(self, space, w_obj, address, scratch):
+        capi.c_double2longdouble(space, space.float_w(w_obj), rffi.cast(rffi.VOIDP, scratch))
+        x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = scratch
+
 
 class CStringConverter(TypeConverter):
     def convert_argument(self, space, w_obj, address):
@@ -949,8 +985,8 @@
 _converters["const float&"]             = ConstFloatRefConverter
 _converters["double"]                   = DoubleConverter
 _converters["const double&"]            = ConstDoubleRefConverter
-#_converters["long double"]              = LongDoubleConverter
-#_converters["const long double&"]       = ConstLongDoubleRefConverter
+_converters["long double"]              = LongDoubleConverter
+_converters["const long double&"]       = ConstLongDoubleRefConverter
 _converters["const char*"]              = CStringConverter
 _converters["void*"]                    = VoidPtrConverter
 _converters["void**"]                   = VoidPtrPtrConverter
@@ -984,7 +1020,12 @@
             _immutable_ = True
             typecode = c_tc
             def __init__(self, space, default):
-                self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+                self.valid_default = False
+                try:
+                    self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+                    self.valid_default = True
+                except Exception:
+                    self.default = rffi.cast(self.c_type, 0)
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
         for name in names:
@@ -1001,7 +1042,12 @@
             _immutable_ = True
             typecode = c_tc
             def __init__(self, space, default):
-                self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+                self.valid_default = False
+                try:
+                    self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+                    self.valid_default = True
+                except Exception:
+                    self.default = rffi.cast(self.c_type, 0)
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
         for name in names:
@@ -1021,7 +1067,12 @@
             _immutable_ = True
             typecode = c_tc
             def __init__(self, space, default):
-                self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
+                self.valid_default = False
+                try:
+                    self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
+                    self.valid_default = True
+                except Exception:
+                    self.default = rffi.cast(self.c_type, 0)
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
         for name in names:
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
@@ -76,9 +76,6 @@
 class NumericExecutorMixin(object):
     _mixin_ = True
 
-    #def _wrap_object(self, space, obj):
-    #    return getattr(space, self.wrapper)(obj)
-
     def execute(self, space, cppmethod, cppthis, num_args, args):
         result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
         return self._wrap_object(space, rffi.cast(self.c_type, result))
@@ -100,13 +97,10 @@
         self.w_item = w_item
         self.do_assign = True
 
-    #def _wrap_object(self, space, obj):
-    #    return getattr(space, self.wrapper)(rffi.cast(self.c_type, obj))
-
     def _wrap_reference(self, space, rffiptr):
         if self.do_assign:
             rffiptr[0] = rffi.cast(self.c_type, self._unwrap_object(space, self.w_item))
-        self.do_assign = False
+            self.do_assign = False
         return self._wrap_object(space, rffiptr[0])    # all paths, for rtyper
 
     def execute(self, space, cppmethod, cppthis, num_args, args):
@@ -119,6 +113,48 @@
         return self._wrap_reference(space,
             rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
 
+class LongDoubleExecutorMixin(object):
+    # Note: not really supported, but returns normal double
+    _mixin_ = True
+
+    def execute(self, space, cppmethod, cppthis, num_args, args):
+        result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
+        return space.newfloat(result)
+
+    def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+        from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible
+
+class LongDoubleExecutor(ffitypes.typeid(rffi.LONGDOUBLE), LongDoubleExecutorMixin, Executor):
+    _immutable_ = True
+    c_stubcall  = staticmethod(capi.c_call_ld)
+
+class LongDoubleRefExecutorMixin(NumericRefExecutorMixin):
+    # Note: not really supported, but returns normal double
+    _mixin_ = True
+
+    def _wrap_reference(self, space, rffiptr):
+        if self.do_assign:
+            capi.c_double2longdouble(space, space.float_w(self.w_item), rffiptr)
+            self.do_assign = False
+            return self.w_item
+        return space.newfloat(capi.c_longdouble2double(space, rffiptr))
+
+    def execute(self, space, cppmethod, cppthis, num_args, args):
+        result = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+        return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
+
+    def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+        jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+        result = rffi.ptradd(buffer, cif_descr.exchange_result)
+        return self._wrap_reference(space,
+            rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
+
+class LongDoubleRefExecutor(ffitypes.typeid(rffi.LONGDOUBLE), LongDoubleRefExecutorMixin, Executor):
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
+
 
 class CStringExecutor(Executor):
     def execute(self, space, cppmethod, cppthis, num_args, args):
@@ -341,6 +377,10 @@
 _executors["void*"]               = PtrTypeExecutor
 _executors["const char*"]         = CStringExecutor
 
+# long double not really supported: narrows to double
+_executors["long double"]          = LongDoubleExecutor
+_executors["long double&"]         = LongDoubleRefExecutor
+
 # special cases (note: 'string' aliases added below)
 _executors["constructor"]         = ConstructorExecutor
 
diff --git a/pypy/module/_cppyy/ffitypes.py b/pypy/module/_cppyy/ffitypes.py
--- a/pypy/module/_cppyy/ffitypes.py
+++ b/pypy/module/_cppyy/ffitypes.py
@@ -296,7 +296,8 @@
     _immutable_fields_ = ['c_type', 'c_ptrtype', 'typecode']
 
     c_type      = rffi.LONGDOUBLE
-    c_ptrtype   = rffi.LONGDOUBLEP
+    # c_ptrtype   = rffi.LONGDOUBLEP   # useless type at this point
+    c_ptrtype   = rffi.VOIDP
     typecode    = 'g'
 
     # long double is not really supported ...
@@ -304,7 +305,7 @@
         return r_longfloat(space.float_w(w_obj))
 
     def _wrap_object(self, space, obj):
-        return space.wrap(obj)
+        return space.newfloat(obj)
 
     def cffi_type(self, space):
         state = space.fromcache(State)
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
@@ -63,6 +63,8 @@
     double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
     RPY_EXTERN
     long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
+    RPY_EXTERN
+    double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
 
     RPY_EXTERN
     void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
@@ -220,9 +222,10 @@
     cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
 
     RPY_EXTERN
-    const char* cppyy_stdvector_valuetype(const char* clname);
+    double cppyy_longdouble2double(void*);
     RPY_EXTERN
-    size_t      cppyy_stdvector_valuesize(const char* clname);
+    void   cppyy_double2longdouble(double, void*);
+
     RPY_EXTERN
     int         cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx);
     RPY_EXTERN
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
@@ -230,8 +230,10 @@
         if self.converters is None:
             try:
                 self._setup(cppthis)
-            except Exception:
-                pass
+            except Exception as e:
+                if self.converters is None:
+                    raise oefmt(self.space.w_SystemError,
+                        "unable to initialize converters (%s)", str(e))
 
         # attempt to call directly through ffi chain
         if useffi and self._funcaddr:
@@ -848,7 +850,7 @@
                 method = self.master.overloads[name]
             else:
             # try to match with run-time instantiations
-                # TODO: logically, this could be used, but in practice, it's proving to
+                # TODO: logically, this could be used, but in practice, it's proving too
                 #  greedy ... maybe as a last resort?
                 #for cppol in self.master.overloads.values():
                 #    try:
@@ -1221,6 +1223,12 @@
         self.datamembers[name] = new_dm
         return new_dm
 
+    @unwrap_spec(name='text')
+    def has_enum(self, name):
+        if capi.c_is_enum(self.space, self.name+'::'+name):
+            return self.space.w_True
+        return self.space.w_False
+
     def _encode_dm_dimensions(self, idata):
         # encode dimensions (TODO: this is ugly, but here's where the info is)
         dims = []
@@ -1269,6 +1277,8 @@
 
     def _make_datamember(self, dm_name, dm_idx):
         type_name = capi.c_datamember_type(self.space, self, dm_idx)
+        if capi.c_is_enum_data(self.space, self, dm_idx):
+            type_name = capi.c_resolve_enum(self.space, type_name)
         offset = capi.c_datamember_offset(self.space, self, dm_idx)
         if offset == -1:
             raise self.missing_attribute_error(dm_name)
@@ -1326,6 +1336,7 @@
     get_datamember_names = interp2app(W_CPPNamespaceDecl.get_datamember_names),
     get_datamember = interp2app(W_CPPNamespaceDecl.get_datamember),
     is_namespace = interp2app(W_CPPNamespaceDecl.is_namespace),
+    has_enum = interp2app(W_CPPNamespaceDecl.has_enum),
     __cppname__ = interp_attrproperty('name', W_CPPNamespaceDecl, wrapfn="newtext"),
     __dispatch__ = interp2app(W_CPPNamespaceDecl.scope__dispatch__),
     __dir__ = interp2app(W_CPPNamespaceDecl.ns__dir__),
@@ -1482,6 +1493,7 @@
     get_datamember_names = interp2app(W_CPPClassDecl.get_datamember_names),
     get_datamember = interp2app(W_CPPClassDecl.get_datamember),
     is_namespace = interp2app(W_CPPClassDecl.is_namespace),
+    has_enum = interp2app(W_CPPClassDecl.has_enum),
     __cppname__ = interp_attrproperty('name', W_CPPClassDecl, wrapfn="newtext"),
     __dispatch__ = interp2app(W_CPPClassDecl.scope__dispatch__)
 )
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
@@ -57,7 +57,7 @@
     itemaddress = interp2app(W_LowLevelView.descr_itemaddress),
     reshape     = interp2app(W_LowLevelView.reshape),
 )
-W_ArrayInstance.typedef.acceptable_as_base_class = False
+W_LowLevelView.typedef.acceptable_as_base_class = False
 
 
 class W_ArrayOfInstances(W_Root):
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
@@ -333,6 +333,11 @@
         except AttributeError:
             pass
 
+    # enum type
+    if not cppitem:
+        if scope.__cppdecl__.has_enum(name):
+            pycppitem = int
+
     if pycppitem is not None:      # pycppitem could be a bound C++ NULL, so check explicitly for Py_None
         return pycppitem
 
@@ -361,18 +366,19 @@
     return '', name
 
 # pythonization by decoration (move to their own file?)
-def python_style_getitem(self, idx):
+def python_style_getitem(self, _idx):
     # python-style indexing: check for size and allow indexing from the back
-    try:
-        sz = len(self)
+    sz = len(self)
+    idx = _idx
+    if isinstance(idx, int):
         if idx < 0: idx = sz + idx
-        if idx < sz:
+        if 0 <= idx < sz:
             return self._getitem__unchecked(idx)
-        raise IndexError(
-            'index out of range: %d requested for %s of size %d' % (idx, str(self), sz))
-    except TypeError:
-        pass
-    return self._getitem__unchecked(idx)
+        else:
+            raise IndexError(
+                'index out of range: %s requested for %s of size %d' % (str(idx), str(self), sz))
+    # may fail for the same reasons as above, but will now give proper error message
+    return self._getitem__unchecked(_idx)
 
 def python_style_sliceable_getitem(self, slice_or_idx):
     if type(slice_or_idx) == slice:
@@ -380,8 +386,7 @@
         nseq += [python_style_getitem(self, i) \
                     for i in range(*slice_or_idx.indices(len(self)))]
         return nseq
-    else:
-        return python_style_getitem(self, slice_or_idx)
+    return python_style_getitem(self, slice_or_idx)
 
 def _pythonize(pyclass, name):
     # general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent
@@ -430,8 +435,8 @@
     # map begin()/end() protocol to iter protocol on STL(-like) classes, but
     # 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 not (0 <= name.find('vector<bool') <= 5):
+    add_checked_item = False
+    if name.find('std::vector', 0, 11) != 0:
         if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
             if _cppyy._scope_byname(name+'::iterator') or \
                     _cppyy._scope_byname(name+'::const_iterator'):
@@ -443,10 +448,12 @@
                     i.__destruct__()
                     raise StopIteration
                 pyclass.__iter__ = __iter__
-            # else: rely on numbered iteration
+            else:
+                # rely on numbered iteration
+                add_checked_item = True
 
     # add python collection based initializer
-    if 0 <= name.find('vector') <= 5:
+    if name.find('std::vector', 0, 11) == 0:
         pyclass.__real_init__ = pyclass.__init__
         def vector_init(self, *args):
             if len(args) == 1 and isinstance(args[0], (tuple, list)):
@@ -468,13 +475,17 @@
                 return arr
             pyclass.data = data_with_len
 
-    # combine __getitem__ and __len__ to make a pythonized __getitem__
-    if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
-        pyclass._getitem__unchecked = pyclass.__getitem__
-        if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
-            pyclass.__getitem__ = python_style_sliceable_getitem
-        else:
-            pyclass.__getitem__ = python_style_getitem
+    # TODO: must be a simpler way to check (or at least hook these to a namespace
+    # std specific pythonizor)
+    if add_checked_item or name.find('std::vector', 0, 11) == 0 or \
+            name.find('std::array', 0, 11) == 0 or name.find('std::deque', 0, 10) == 0:
+        # combine __getitem__ and __len__ to make a pythonized __getitem__
+        if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
+            pyclass._getitem__unchecked = pyclass.__getitem__
+            if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
+                pyclass.__getitem__ = python_style_sliceable_getitem
+            else:
+                pyclass.__getitem__ = python_style_getitem
 
     # string comparisons
     if name == _cppyy._std_string_name():
diff --git a/pypy/module/_cppyy/src/dummy_backend.cxx b/pypy/module/_cppyy/src/dummy_backend.cxx
--- a/pypy/module/_cppyy/src/dummy_backend.cxx
+++ b/pypy/module/_cppyy/src/dummy_backend.cxx
@@ -62,6 +62,7 @@
         m_name(name), m_argtypes(argtypes), m_returntype(returntype), m_type(mtype) {}
     std::string m_name;
     std::vector<std::string> m_argtypes;
+    std::vector<std::string> m_argdefaults;
     std::string m_returntype;
     EMethodType m_type;
 };
@@ -376,6 +377,13 @@
         PUBLIC_CPPYY_STATIC_DATA(enum,    CppyyTestData::EWhat);
         PUBLIC_CPPYY_STATIC_DATA(voidp,   void*);
 
+      // default tester for long double
+        argtypes.clear();
+        argtypes.push_back("long double");
+        methods.push_back(new Cppyy_PseudoMethodInfo("get_ldouble_def", argtypes, "long double"));
+        methods.back()->m_argdefaults.push_back("aap_t(1)");
+        s_methods["CppyyTestData::get_ldouble_def"] = methods.back();
+
       // pretend enum values
         data.push_back(Cppyy_PseudoDatambrInfo(
             "kNothing", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kNothing, true));
@@ -416,6 +424,8 @@
 char* cppyy_resolve_name(const char* cppitem_name) {
     if (cppyy_is_enum(cppitem_name))
         return cppstring_to_cstring("internal_enum_type_t");
+    else if (strcmp(cppitem_name, "aap_t") == 0)
+        return cppstring_to_cstring("long double");
     return cppstring_to_cstring(cppitem_name);
 }
 
@@ -520,6 +530,12 @@
     } else if (idx == s_methods["CppyyTestData::set_double_cr"]) {
         assert(self && nargs == 1);
         ((dummy::CppyyTestData*)self)->set_double_cr(*(double*)&((CPPYY_G__value*)args)[0]);
+    } else if (idx == s_methods["CppyyTestData::set_ldouble"]) {
+        assert(self && nargs == 1);
+        ((dummy::CppyyTestData*)self)->set_ldouble(((CPPYY_G__value*)args)[0].obj.ld);
+    } else if (idx == s_methods["CppyyTestData::set_ldouble_cr"]) {
+        assert(self && nargs == 1);
+        ((dummy::CppyyTestData*)self)->set_ldouble_cr(*(long double*)&((CPPYY_G__value*)args)[0]);
     } else {
         assert(!"method unknown in cppyy_call_v");
     }
@@ -794,6 +810,26 @@
     return result;
 }
 
+double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+    double result = 0.;
+    Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
+    if (idx == s_methods["CppyyTestData::get_ldouble_def"]) {
+        if (nargs == 1)
+            result = (double)((dummy::CppyyTestData*)self)->get_ldouble_def(
+                ((CPPYY_G__value*)args)[0].obj.ld);
+        else {
+            assert(self && nargs == 0);
+            result = (double)((dummy::CppyyTestData*)self)->get_ldouble_def();
+        }
+    } else if (idx == s_methods["CppyyTestData::get_ldouble"]) {
+        assert(self && nargs == 0);
+        result = (double)((dummy::CppyyTestData*)self)->get_ldouble();
+    } else {
+        assert(!"method unknown in cppyy_call_nld");
+    }
+    return result;
+}
+
 #define DISPATCH_CALL_R_GET(tpname)                                           \
     else if (idx == s_methods["CppyyTestData::get_"#tpname"_r"]) {            \
         assert(self && nargs == 0);                                           \
@@ -966,14 +1002,16 @@
 }
 
 int cppyy_method_req_args(cppyy_method_t method) {
-    return cppyy_method_num_args(method);
+    return cppyy_method_num_args(method)-((Cppyy_PseudoMethodInfo*)method)->m_argdefaults.size();
 }
 
 char* cppyy_method_arg_type(cppyy_method_t method, int idx) {
     return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_argtypes[idx]);
 }
 
-char* cppyy_method_arg_default(cppyy_method_t, int /* arg_index */) {
+char* cppyy_method_arg_default(cppyy_method_t method, int idx) {
+    if (idx < (int)((Cppyy_PseudoMethodInfo*)method)->m_argdefaults.size())
+        return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_argdefaults[idx]);
     return cppstring_to_cstring("");
 }
 
@@ -1094,13 +1132,30 @@
 }
 
 cppyy_object_t cppyy_charp2stdstring(const char* str, size_t sz) {
-    void* arena = new char[sz];
-    new (arena) std::string(str, sz);
-    return (cppyy_object_t)arena;
+    return (cppyy_object_t)new std::string(str, sz);
+}
+
+const char* cppyy_stdstring2charp(cppyy_object_t ptr, size_t* lsz) {
+    *lsz = ((std::string*)ptr)->size();
+    return ((std::string*)ptr)->data();
 }
 
 cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr) {
-    void* arena = new char[sizeof(std::string)];
-    new (arena) std::string(*(std::string*)ptr);
-    return (cppyy_object_t)arena;
+    return (cppyy_object_t)new std::string(*(std::string*)ptr);
 }
+
+double cppyy_longdouble2double(void* p) {
+    return (double)*(long double*)p;
+}
+
+void cppyy_double2longdouble(double d, void* p) {
+    *(long double*)p = d;
+}
+
+int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx) {
+    return (int)(*(std::vector<bool>*)ptr)[idx];
+}
+
+void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value) {
+    (*(std::vector<bool>*)ptr)[idx] = (bool)value;
+}
diff --git a/pypy/module/_cppyy/test/datatypes.cxx b/pypy/module/_cppyy/test/datatypes.cxx
--- a/pypy/module/_cppyy/test/datatypes.cxx
+++ b/pypy/module/_cppyy/test/datatypes.cxx
@@ -113,6 +113,7 @@
 float                CppyyTestData::get_float()   { return m_float; }
 double               CppyyTestData::get_double()  { return m_double; }
 long double          CppyyTestData::get_ldouble() { return m_ldouble; }
+long double          CppyyTestData::get_ldouble_def(long double ld) { return ld; }
 CppyyTestData::EWhat CppyyTestData::get_enum()    { return m_enum; }
 void*                CppyyTestData::get_voidp()   { return m_voidp; }
 
diff --git a/pypy/module/_cppyy/test/datatypes.h b/pypy/module/_cppyy/test/datatypes.h
--- a/pypy/module/_cppyy/test/datatypes.h
+++ b/pypy/module/_cppyy/test/datatypes.h
@@ -32,6 +32,8 @@
         enum    {E1 = -1};
         enum EE {E2 = -1};
     };
+
+    typedef enum { AA = 1, BB, CC, DD } letter_code;
 }
 
 
@@ -94,6 +96,8 @@
     float                get_float();
     double               get_double();
     long double          get_ldouble();
+    typedef long double aap_t;
+    long double          get_ldouble_def(long double ld = aap_t(1));
     EWhat                get_enum();
     void*                get_voidp();
 
diff --git a/pypy/module/_cppyy/test/datatypes.xml b/pypy/module/_cppyy/test/datatypes.xml
--- a/pypy/module/_cppyy/test/datatypes.xml
+++ b/pypy/module/_cppyy/test/datatypes.xml
@@ -6,6 +6,7 @@
   <enum name="EFruit" />
   <enum name="EnumSpace::E" />
   <class name="EnumSpace::EnumClass" />
+  <enum name="EnumSpace::letter_code" />
 
   <function pattern="get_*" />
   <function pattern="set_*" />
diff --git a/pypy/module/_cppyy/test/stltypes.h b/pypy/module/_cppyy/test/stltypes.h
--- a/pypy/module/_cppyy/test/stltypes.h
+++ b/pypy/module/_cppyy/test/stltypes.h
@@ -4,12 +4,23 @@
 #include <utility>
 #include <vector>
 
+
 //- basic example class
 class just_a_class {
 public:
     int m_i;
 };
 
+// enum for vector of enums setitem tests
+enum VecTestEnum {
+    EVal1 = 1, EVal2 = 3
+};
+
+namespace VecTestEnumNS {
+    enum VecTestEnum { EVal1 = 5, EVal2 = 42 };
+}
+
+
 //- class with lots of std::string handling
 class stringy_class {
 public:
@@ -31,35 +42,15 @@
 class stl_like_class {
 public: 
    no_dict_available* begin() { return 0; }
-   no_dict_available* end() { return 0; }
+   no_dict_available* end() { return (no_dict_available*)1; }
    int size() { return 4; }
    int operator[](int i) { return i; }
    std::string operator[](double) { return "double"; }
    std::string operator[](const std::string&) { return "string"; }
 };      
 
-
-//- instantiations of used STL types
 namespace {
-
     stl_like_class<int> stlc_1;
-
-} // unnamed namespace
-
-
-// comps for int only to allow testing: normal use of vector is looping over a
-// range-checked version of __getitem__
-#if defined(__clang__) && defined(__APPLE__)
-namespace std {
-#define ns_prefix std::
-#elif defined(__GNUC__) || defined(__GNUG__)
-namespace __gnu_cxx {
-#define ns_prefix
-#endif
-extern template bool ns_prefix operator==(const std::vector<int>::iterator&,
-                         const std::vector<int>::iterator&);
-extern template bool ns_prefix operator!=(const std::vector<int>::iterator&,
-                         const std::vector<int>::iterator&);
 }
 
 
@@ -67,6 +58,8 @@
 namespace ArrayTest {
 
 struct Point {
+    Point() : px(0), py(0) {}
+    Point(int x, int y) : px(x), py(y) {}
     int px, py;
 };
 
diff --git a/pypy/module/_cppyy/test/stltypes.xml b/pypy/module/_cppyy/test/stltypes.xml
--- a/pypy/module/_cppyy/test/stltypes.xml
+++ b/pypy/module/_cppyy/test/stltypes.xml
@@ -1,6 +1,9 @@
 <lcgdict>
 
   <class name="just_a_class" />
+  <enum name="VecTestEnum" />
+  <namespace name="VecTestEnumNS" />
+  <enum name="VecTestEnumNS::VecTestEnum" />
   <class name="stringy_class" />
   <class pattern="stl_like_class<*>" />
 
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
@@ -56,10 +56,11 @@
         assert round(c.m_double         + 77., 11) == 0
         assert round(c.get_double_cr()  + 77., 11) == 0
         assert round(c.get_double_r()   + 77., 11) == 0
-        #assert round(c.m_ldouble        + 88., 24) == 0
-        #assert round(c.get_ldouble_cr() + 88., 24) == 0
-        #assert round(c.get_ldouble_r()  + 88., 24) == 0
-        assert round(c.m_double + 77., 8) == 0
+        assert round(c.m_ldouble        + 88., 24) == 0
+        assert round(c.get_ldouble_cr() + 88., 24) == 0
+        assert round(c.get_ldouble_r()  + 88., 24) == 0
+        assert round(c.get_ldouble_def()  -1., 24) == 0
+        assert round(c.get_ldouble_def(2) -2., 24) == 0
 
         """# complex<double> type
         assert type(c.get_complex()) == complex
@@ -187,16 +188,20 @@
             assert eval('c.m_%s' % names[i]) == 3*i
 
         # float types through functions
-        c.set_float( 0.123 );  assert round(c.get_float()  - 0.123, 5) == 0
-        c.set_double( 0.456 ); assert round(c.get_double() - 0.456, 8) == 0
+        c.set_float(0.123);   assert round(c.get_float()   - 0.123, 5) == 0
+        c.set_double(0.456);  assert round(c.get_double()  - 0.456, 8) == 0
+        c.set_ldouble(0.789); assert round(c.get_ldouble() - 0.789, 8) == 0
 
         # float types through data members
-        c.m_float = 0.123;      assert round(c.get_float()  - 0.123, 5) == 0
-        c.set_float(0.234);     assert round(c.m_float      - 0.234, 5) == 0
-        c.set_float_cr(0.456);  assert round(c.m_float      - 0.456, 5) == 0
-        c.m_double = 0.678;     assert round(c.get_double() - 0.678, 8) == 0
-        c.set_double(0.890);    assert round(c.m_double     - 0.890, 8) == 0
-        c.set_double_cr(0.012); assert round(c.m_double     - 0.012, 8) == 0
+        c.m_float = 0.123;       assert round(c.get_float()   - 0.123, 5) == 0
+        c.set_float(0.234);      assert round(c.m_float       - 0.234, 5) == 0
+        c.set_float_cr(0.456);   assert round(c.m_float       - 0.456, 5) == 0
+        c.m_double = 0.678;      assert round(c.get_double()  - 0.678, 8) == 0
+        c.set_double(0.890);     assert round(c.m_double      - 0.890, 8) == 0
+        c.set_double_cr(0.012);  assert round(c.m_double      - 0.012, 8) == 0
+        c.m_ldouble = 0.876;     assert round(c.get_ldouble() - 0.876, 8) == 0
+        c.set_ldouble(0.098);    assert round(c.m_ldouble     - 0.098, 8) == 0
+        c.set_ldouble_cr(0.210); assert round(c.m_ldouble     - 0.210, 8) == 0
 
         # arrays; there will be pointer copies, so destroy the current ones
         c.destroy_arrays()
@@ -295,10 +300,12 @@
         assert CppyyTestData.s_ullong   ==  404
 
         # floating point types
-        assert round(CppyyTestData.s_float  + 606., 5) == 0
-        assert round(c.s_float              + 606., 5) == 0
-        assert round(CppyyTestData.s_double + 707., 8) == 0
-        assert round(c.s_double             + 707., 8) == 0
+        assert round(CppyyTestData.s_float   + 606., 5) == 0
+        assert round(c.s_float               + 606., 5) == 0
+        assert round(CppyyTestData.s_double  + 707., 8) == 0
+        assert round(c.s_double              + 707., 8) == 0
+        assert round(CppyyTestData.s_ldouble + 808., 8) == 0
+        assert round(c.s_ldouble             + 808., 8) == 0
 
         c.__destruct__()
 
@@ -363,6 +370,10 @@
         assert CppyyTestData.s_double             == -math.pi
         CppyyTestData.s_double                     =  math.pi
         assert c.s_double                         ==  math.pi
+        c.s_ldouble                                = -math.pi
+        assert CppyyTestData.s_ldouble            == -math.pi
+        CppyyTestData.s_ldouble                    =  math.pi
+        assert c.s_ldouble                        ==  math.pi
 
         c.__destruct__()
 
@@ -499,6 +510,11 @@
         assert gbl.EnumSpace.EnumClass.E1 == -1   # anonymous
         assert gbl.EnumSpace.EnumClass.E2 == -1   # named type
 
+        # typedef enum
+        assert gbl.EnumSpace.letter_code
+        assert gbl.EnumSpace.AA == 1
+        assert gbl.EnumSpace.BB == 2
+
     def test11_string_passing(self):
         """Test passing/returning of a const char*"""
 
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
@@ -215,6 +215,26 @@
         assert len(vb[4:8]) == 4
         assert list(vb[4:8]) == [False]*3+[True]
 
+    def test08_vector_enum(self):
+        """Usability of std::vector<> of some enums"""
+
+        import _cppyy as cppyy
+
+        # TODO: would like to use cppyy.gbl.VecTestEnum but that's an int
+        assert cppyy.gbl.VecTestEnum
+        ve = cppyy.gbl.std.vector['VecTestEnum']()
+        ve.push_back(cppyy.gbl.EVal1);
+        assert ve[0] == 1
+        ve[0] = cppyy.gbl.EVal2
+        assert ve[0] == 3
+
+        assert cppyy.gbl.VecTestEnumNS.VecTestEnum
+        ve = cppyy.gbl.std.vector['VecTestEnumNS::VecTestEnum']()
+        ve.push_back(cppyy.gbl.VecTestEnumNS.EVal1);
+        assert ve[0] == 5
+        ve[0] = cppyy.gbl.VecTestEnumNS.EVal2
+        assert ve[0] == 42
+
 
 class AppTestSTLSTRING:
     spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -484,10 +504,11 @@
         stl_like_class = cppyy.gbl.stl_like_class
 
         a = stl_like_class(int)()
-        for i in a:
-            pass
+        assert len(a) == 4
+        for i, j in enumerate(a):
+            assert i == j
 
-        assert i == 3
+        assert i == len(a)-1
 
 
 class AppTestSTLITERATOR:
@@ -594,9 +615,9 @@
     def test03_array_of_pointer_to_pods(self):
         """Usage of std::array of pointer to PODs"""
 
-        import cppyy
-        from cppyy import gbl
-        from cppyy.gbl import std
+        import _cppyy as cppyy
+        gbl = cppyy.gbl
+        std = cppyy.gbl.std
 
         ll = [gbl.ArrayTest.Point() for i in range(4)]
         for i in range(len(ll)):


More information about the pypy-commit mailing list