Author: Wim Lavrijsen <wlavrij...@lbl.gov>
Branch: 
Changeset: r94435:e50e11af23f1
Date: 2018-04-23 19:57 -0700
http://bitbucket.org/pypy/pypy/changeset/e50e11af23f1/

Log:    merge cppyy-packaging: move to latest backend (0.6.0) and support
        exceptions through wrappers

diff --git a/pypy/module/_cppyy/__init__.py b/pypy/module/_cppyy/__init__.py
--- a/pypy/module/_cppyy/__init__.py
+++ b/pypy/module/_cppyy/__init__.py
@@ -13,7 +13,7 @@
         '_set_function_generator': 'interp_cppyy.set_function_generator',
         '_register_class'        : 'interp_cppyy.register_class',
         '_get_nullptr'           : 'interp_cppyy.get_nullptr',
-        'CPPClassBase'           : 'interp_cppyy.W_CPPClass',
+        'CPPInstanceBase'        : 'interp_cppyy.W_CPPInstance',
         'addressof'              : 'interp_cppyy.addressof',
         '_bind_object'           : 'interp_cppyy._bind_object',
         'bind_object'            : 'interp_cppyy.bind_object',
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
@@ -121,11 +121,11 @@
 
         # TODO: the following need to match up with the globally defined C_XYZ 
low-level
         # types (see capi/__init__.py), but by using strings here, that isn't 
guaranteed
-        c_opaque_ptr = state.c_ulong
+        c_opaque_ptr = state.c_ulong    # not ptrdiff_t (which is signed)
  
         c_scope       = c_opaque_ptr
         c_type        = c_scope
-        c_object      = c_opaque_ptr
+        c_object      = c_opaque_ptr    # not voidp (to stick with one handle 
type)
         c_method      = c_opaque_ptr
         c_index       = state.c_long
         c_index_array = state.c_voidp
@@ -150,16 +150,17 @@
 
         self.capi_call_ifaces = {
             # name to opaque C++ scope representation
-            'num_scopes'               : ([c_scope],                  c_int),
-            'scope_name'               : ([c_scope, c_int],           
c_ccharp),
-
             'resolve_name'             : ([c_ccharp],                 
c_ccharp),
+            'resolve_enum'             : ([c_ccharp],                 
c_ccharp),
             'get_scope'                : ([c_ccharp],                 c_scope),
             'actual_class'             : ([c_type, c_object],         c_type),
+            'size_of_klass'            : ([c_type],                   
c_size_t),
+            'size_of_type'             : ([c_ccharp],                 
c_size_t),
 
             # memory management
             'allocate'                 : ([c_type],                   
c_object),
             'deallocate'               : ([c_type, c_object],         c_void),
+            'construct'                : ([c_type],                   
c_object),
             'destruct'                 : ([c_type, c_object],         c_void),
 
             # method/function dispatching
@@ -182,7 +183,8 @@
             'constructor'  : ([c_method, c_object, c_int, c_voidp],   
c_object),
             'call_o'       : ([c_method, c_object, c_int, c_voidp, c_type],    
 c_object),
 
-            'get_function_address'     : ([c_scope, c_index],         
c_voidp), # TODO: verify
+            'function_address_from_index'  : ([c_scope, c_index],     
c_voidp), # TODO: verify
+            'function_address_from_method' : ([c_method],             
c_voidp), # id.
 
             # handling of function argument buffer
             'allocate_function_args'   : ([c_int],                    c_voidp),
@@ -196,6 +198,8 @@
             'is_abstract'              : ([c_type],                   c_int),
             'is_enum'                  : ([c_ccharp],                 c_int),
 
+            'get_all_cpp_names'        : ([c_scope, c_voidp],         
c_voidp), # const char**
+
             # type/class reflection information
             'final_name'               : ([c_type],                   
c_ccharp),
             'scoped_final_name'        : ([c_type],                   
c_ccharp),
@@ -208,10 +212,10 @@
 
             # method/function reflection information
             'num_methods'              : ([c_scope],                  c_int),
-            'method_index_at'          : ([c_scope, c_int],           c_index),
             'method_indices_from_name' : ([c_scope, c_ccharp],        
c_index_array),
 
             'method_name'              : ([c_scope, c_index],         
c_ccharp),
+            'method_mangled_name'      : ([c_scope, c_index],         
c_ccharp),
             'method_result_type'       : ([c_scope, c_index],         
c_ccharp),
             'method_num_args'          : ([c_scope, c_index],         c_int),
             'method_req_args'          : ([c_scope, c_index],         c_int),
@@ -219,7 +223,9 @@
             'method_arg_default'       : ([c_scope, c_index, c_int],  
c_ccharp),
             'method_signature'         : ([c_scope, c_index, c_int],  
c_ccharp),
             'method_prototype'         : ([c_scope, c_index, c_int],  
c_ccharp),
+            'is_const_method'          : ([c_method],                 c_int),
 
+            'exists_method_template'   : ([c_scope, c_ccharp],        c_int),
             'method_is_template'       : ([c_scope, c_index],         c_int),
             'method_num_template_args' : ([c_scope, c_index],         c_int),
             'method_template_arg_name' : ([c_scope, c_index, c_index],         
 c_ccharp),
@@ -228,7 +234,9 @@
             'get_global_operator'      : ([c_scope, c_scope, c_scope, 
c_ccharp],   c_index),
 
             # method properties
+            'is_public_method'         : ([c_type, c_index],          c_int),
             'is_constructor'           : ([c_type, c_index],          c_int),
+            'is_destructor'            : ([c_type, c_index],          c_int),
             'is_staticmethod'          : ([c_type, c_index],          c_int),
 
             # data member reflection information
@@ -236,12 +244,14 @@
             'datamember_name'          : ([c_scope, c_int],           
c_ccharp),
             'datamember_type'          : ([c_scope, c_int],           
c_ccharp),
             'datamember_offset'        : ([c_scope, c_int],           
c_ptrdiff_t),
-
             'datamember_index'         : ([c_scope, c_ccharp],        c_int),
 
             # data member properties
             'is_publicdata'            : ([c_scope, c_int],           c_int),
             'is_staticdata'            : ([c_scope, c_int],           c_int),
+            'is_const_data'            : ([c_scope, c_int],           c_int),
+            'is_enum_data'             : ([c_scope, c_int],           c_int),
+            'get_dimension_size'       : ([c_scope, c_int, c_int],    c_int),
 
             # misc helpers
             'strtoll'                  : ([c_ccharp],                 c_llong),
@@ -328,25 +338,27 @@
     return rffi.cast(rffi.CCHARP, ptr)
 
 # name to opaque C++ scope representation ------------------------------------
-def c_num_scopes(space, cppscope):
-    return space.int_w(call_capi(space, 'num_scopes', 
[_ArgH(cppscope.handle)]))
-def c_scope_name(space, cppscope, iscope):
-    args = [_ArgH(cppscope.handle), _ArgL(iscope)]
-    return charp2str_free(space, call_capi(space, 'scope_name', args))
-
 def c_resolve_name(space, name):
     return charp2str_free(space, call_capi(space, 'resolve_name', 
[_ArgS(name)]))
+def c_resolve_enum(space, name):
+    return charp2str_free(space, call_capi(space, 'resolve_enum', 
[_ArgS(name)]))
 def c_get_scope_opaque(space, name):
     return rffi.cast(C_SCOPE, space.uint_w(call_capi(space, 'get_scope', 
[_ArgS(name)])))
 def c_actual_class(space, cppclass, cppobj):
     args = [_ArgH(cppclass.handle), _ArgH(cppobj)]
     return rffi.cast(C_TYPE, space.uint_w(call_capi(space, 'actual_class', 
args)))
+def c_size_of_klass(space, cppclass):
+    return _cdata_to_size_t(space, call_capi(space, 'size_of_klass', 
[_ArgH(cppclass.handle)]))
+def c_size_of_type(space, name):
+    return _cdata_to_size_t(space, call_capi(space, 'size_of_type', 
[_ArgS(name)]))
 
 # memory management ----------------------------------------------------------
 def c_allocate(space, cppclass):
     return _cdata_to_cobject(space, call_capi(space, 'allocate', 
[_ArgH(cppclass.handle)]))
 def c_deallocate(space, cppclass, cppobject):
     call_capi(space, 'deallocate', [_ArgH(cppclass.handle), _ArgH(cppobject)])
+def c_construct(space, cppclass):
+    return _cdata_to_cobject(space, call_capi(space, 'construct', 
[_ArgH(cppclass.handle)]))
 def c_destruct(space, cppclass, cppobject):
     call_capi(space, 'destruct', [_ArgH(cppclass.handle), _ArgH(cppobject)])
 
@@ -391,7 +403,7 @@
         w_cstr = call_capi(space, 'call_s',
             [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs),
              _ArgP(rffi.cast(rffi.VOIDP, length))])
-        cstr_len = intmask(length[0])
+        cstr_len = int(intmask(length[0]))
     finally:
         lltype.free(length, flavor='raw')
     return _cdata_to_ccharp(space, w_cstr), cstr_len
@@ -403,10 +415,13 @@
     args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs), 
_ArgH(cppclass.handle)]
     return _cdata_to_cobject(space, call_capi(space, 'call_o', args))
 
-def c_get_function_address(space, cppscope, index):
+def c_function_address_from_index(space, cppscope, index):
     args = [_ArgH(cppscope.handle), _ArgL(index)]
     return rffi.cast(C_FUNC_PTR,
-        _cdata_to_ptr(space, call_capi(space, 'get_function_address', args)))
+        _cdata_to_ptr(space, call_capi(space, 'function_address_from_index', 
args)))
+def c_function_address_from_method(space, cppmethod):
+    return rffi.cast(C_FUNC_PTR,
+        _cdata_to_ptr(space, call_capi(space, 'function_address_from_method', 
_ArgH(cppmethod))))
 
 # handling of function argument buffer ---------------------------------------
 def c_allocate_function_args(space, size):
@@ -430,6 +445,23 @@
 def c_is_enum(space, name):
     return space.bool_w(call_capi(space, 'is_enum', [_ArgS(name)]))
 
+def c_get_all_cpp_names(space, scope):
+    sz = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw', zero=True)
+    try:
+        args = [_ArgH(scope.handle), _ArgP(rffi.cast(rffi.VOIDP, sz))]
+        rawnames = rffi.cast(rffi.CCHARPP,
+            _cdata_to_ptr(space, call_capi(space, 'get_all_cpp_names', args)))
+        count = int(intmask(sz[0]))
+    finally:
+        lltype.free(sz, flavor='raw')
+    allnames = []
+    for i in range(count):
+        pystr = rffi.charp2str(rawnames[i])
+        c_free(space, rffi.cast(rffi.VOIDP, rawnames[i])) # c_free defined 
below
+        allnames.append(pystr)
+    c_free(space, rffi.cast(rffi.VOIDP, rawnames))        # id.
+    return allnames
+
 # type/class reflection information ------------------------------------------
 def c_final_name(space, cpptype):
     return charp2str_free(space, call_capi(space, 'final_name', 
[_ArgH(cpptype)]))
@@ -462,13 +494,10 @@
 def c_num_methods(space, cppscope):
     args = [_ArgH(cppscope.handle)]
     return space.int_w(call_capi(space, 'num_methods', args))
-def c_method_index_at(space, cppscope, imethod):
-    args = [_ArgH(cppscope.handle), _ArgL(imethod)]
-    return space.int_w(call_capi(space, 'method_index_at', args))
 def c_method_indices_from_name(space, cppscope, name):
     args = [_ArgH(cppscope.handle), _ArgS(name)]
     indices = rffi.cast(C_INDEX_ARRAY,
-                        _cdata_to_ptr(space, call_capi(space, 
'method_indices_from_name', args)))
+        _cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', 
args)))
     if not indices:
         return []
     py_indices = []
@@ -506,6 +535,9 @@
     args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(show_formalargs)]
     return charp2str_free(space, call_capi(space, 'method_prototype', args))
 
+def c_exists_method_template(space, cppscope, name):
+    args = [_ArgH(cppscope.handle), _ArgS(name)]
+    return space.bool_w(call_capi(space, 'exists_method_template', args))
 def c_method_is_template(space, cppscope, index):
     args = [_ArgH(cppscope.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'method_is_template', args))
@@ -531,9 +563,15 @@
     return rffi.cast(WLAVC_INDEX, -1)
 
 # method properties ----------------------------------------------------------
+def c_is_public_method(space, cppclass, index):
+    args = [_ArgH(cppclass.handle), _ArgL(index)]
+    return space.bool_w(call_capi(space, 'is_public_method', args))
 def c_is_constructor(space, cppclass, index):
     args = [_ArgH(cppclass.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'is_constructor', args))
+def c_is_destructor(space, cppclass, index):
+    args = [_ArgH(cppclass.handle), _ArgL(index)]
+    return space.bool_w(call_capi(space, 'is_destructor', args))
 def c_is_staticmethod(space, cppclass, index):
     args = [_ArgH(cppclass.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'is_staticmethod', args))
@@ -562,6 +600,15 @@
 def c_is_staticdata(space, cppscope, datamember_index):
     args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return space.bool_w(call_capi(space, 'is_staticdata', args))
+def c_is_const_data(space, cppscope, datamember_index):
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+    return space.bool_w(call_capi(space, 'is_const_data', args))
+def c_is_enum_data(space, cppscope, datamember_index):
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+    return space.bool_w(call_capi(space, 'is_enum_data', args))
+def c_get_dimension_size(space, cppscope, datamember_index, dim_idx):
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index), _ArgL(dim_idx)]
+    return space.bool_w(call_capi(space, 'get_dimension_size', args))
 
 # misc helpers ---------------------------------------------------------------
 def c_strtoll(space, svalue):
@@ -585,7 +632,7 @@
     try:
         w_cstr = call_capi(space, 'stdstring2charp',
             [_ArgH(cppstr), _ArgP(rffi.cast(rffi.VOIDP, sz))])
-        cstr_len = intmask(sz[0])
+        cstr_len = int(intmask(sz[0]))
     finally:
         lltype.free(sz, flavor='raw')
     return rffi.charpsize2str(_cdata_to_ccharp(space, w_cstr), cstr_len)
@@ -607,7 +654,7 @@
     """Return a python string taking into account \0"""
 
     from pypy.module._cppyy import interp_cppyy
-    cppstr = space.interp_w(interp_cppyy.W_CPPClass, w_self, can_be_None=False)
+    cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, 
can_be_None=False)
     return space.newtext(c_stdstring2charp(space, cppstr._rawobject))
 
 # setup pythonizations for later use at run-time
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
@@ -22,8 +22,8 @@
 
 
 def get_rawobject(space, w_obj, can_be_None=True):
-    from pypy.module._cppyy.interp_cppyy import W_CPPClass
-    cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=can_be_None)
+    from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+    cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=can_be_None)
     if cppinstance:
         rawobject = cppinstance.get_rawobject()
         assert lltype.typeOf(rawobject) == capi.C_OBJECT
@@ -31,15 +31,15 @@
     return capi.C_NULL_OBJECT
 
 def set_rawobject(space, w_obj, address):
-    from pypy.module._cppyy.interp_cppyy import W_CPPClass
-    cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
+    from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+    cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
     if cppinstance:
         assert lltype.typeOf(cppinstance._rawobject) == capi.C_OBJECT
         cppinstance._rawobject = rffi.cast(capi.C_OBJECT, address)
 
 def get_rawobject_nonnull(space, w_obj):
-    from pypy.module._cppyy.interp_cppyy import W_CPPClass
-    cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
+    from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+    cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
     if cppinstance:
         cppinstance._nullcheck()
         rawobject = cppinstance.get_rawobject()
@@ -502,8 +502,8 @@
         self.clsdecl = clsdecl
 
     def _unwrap_object(self, space, w_obj):
-        from pypy.module._cppyy.interp_cppyy import W_CPPClass
-        if isinstance(w_obj, W_CPPClass):
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+        if isinstance(w_obj, W_CPPInstance):
             from pypy.module._cppyy.interp_cppyy import 
INSTANCE_FLAGS_IS_R_VALUE
             if w_obj.flags & INSTANCE_FLAGS_IS_R_VALUE:
                 # reject moves as all are explicit
@@ -534,8 +534,8 @@
 class InstanceMoveConverter(InstanceRefConverter):
     def _unwrap_object(self, space, w_obj):
         # moving is same as by-ref, but have to check that move is allowed
-        from pypy.module._cppyy.interp_cppyy import W_CPPClass, 
INSTANCE_FLAGS_IS_R_VALUE
-        if isinstance(w_obj, W_CPPClass):
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance, 
INSTANCE_FLAGS_IS_R_VALUE
+        if isinstance(w_obj, W_CPPInstance):
             if w_obj.flags & INSTANCE_FLAGS_IS_R_VALUE:
                 w_obj.flags &= ~INSTANCE_FLAGS_IS_R_VALUE
                 return InstanceRefConverter._unwrap_object(self, space, w_obj)
@@ -598,8 +598,8 @@
         raise FastCallNotPossible
 
     def finalize_call(self, space, w_obj, call_local):
-        from pypy.module._cppyy.interp_cppyy import W_CPPClass
-        assert isinstance(w_obj, W_CPPClass)
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+        assert isinstance(w_obj, W_CPPInstance)
         r = rffi.cast(rffi.VOIDPP, call_local)
         w_obj._rawobject = rffi.cast(capi.C_OBJECT, r[0])
 
@@ -617,8 +617,8 @@
         InstanceConverter.__init__(self, space, cppclass)
 
     def _unwrap_object(self, space, w_obj):
-        from pypy.module._cppyy.interp_cppyy import W_CPPClass
-        if isinstance(w_obj, W_CPPClass):
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+        if isinstance(w_obj, W_CPPInstance):
             arg = InstanceConverter._unwrap_object(self, space, w_obj)
             return capi.c_stdstring2stdstring(space, arg)
         else:
@@ -749,8 +749,6 @@
             return InstancePtrPtrConverter(space, clsdecl)
         elif compound == "":
             return InstanceConverter(space, clsdecl)
-    elif capi.c_is_enum(space, clean_name):
-        return _converters['unsigned'](space, default)
 
     #   5) void* or void converter (which fails on use)
     if 0 <= compound.find('*'):
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
@@ -289,8 +289,6 @@
             return InstancePtrExecutor(space, cppclass)
         elif compound == '**' or compound == '*&':
             return InstancePtrPtrExecutor(space, cppclass)
-    elif capi.c_is_enum(space, clean_name):
-        return _executors['internal_enum_type_t'](space, None)
 
     # 4) additional special cases
     if compound == '*':
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
@@ -8,26 +8,29 @@
 extern "C" {
 #endif // ifdef __cplusplus
 
-    typedef unsigned long cppyy_scope_t;
+    typedef ptrdiff_t     cppyy_scope_t;
     typedef cppyy_scope_t cppyy_type_t;
-    typedef unsigned long cppyy_object_t;
-    typedef unsigned long cppyy_method_t;
+    typedef void*         cppyy_object_t;
+    typedef ptrdiff_t     cppyy_method_t;
+
     typedef long          cppyy_index_t;
     typedef void*         cppyy_funcaddr_t;
 
+    typedef unsigned long cppyy_exctype_t;
+
     /* name to opaque C++ scope representation 
-------------------------------- */
     RPY_EXTERN
-    int cppyy_num_scopes(cppyy_scope_t parent);
+    char* cppyy_resolve_name(const char* cppitem_name);
     RPY_EXTERN
-    char* cppyy_scope_name(cppyy_scope_t parent, cppyy_index_t iscope);
-    RPY_EXTERN
-    char* cppyy_resolve_name(const char* cppitem_name);
+    char* cppyy_resolve_enum(const char* enum_type);
     RPY_EXTERN
     cppyy_scope_t cppyy_get_scope(const char* scope_name);
     RPY_EXTERN
     cppyy_type_t cppyy_actual_class(cppyy_type_t klass, cppyy_object_t obj);
     RPY_EXTERN
-    size_t cppyy_size_of(cppyy_type_t klass);
+    size_t cppyy_size_of_klass(cppyy_type_t klass);
+    RPY_EXTERN
+    size_t cppyy_size_of_type(const char* type_name);
 
     /* memory management 
------------------------------------------------------ */
     RPY_EXTERN
@@ -35,48 +38,53 @@
     RPY_EXTERN
     void cppyy_deallocate(cppyy_type_t type, cppyy_object_t self);
     RPY_EXTERN
+    cppyy_object_t cppyy_construct(cppyy_type_t type);
+    RPY_EXTERN
     void cppyy_destruct(cppyy_type_t type, cppyy_object_t self);
 
     /* method/function dispatching 
-------------------------------------------- */
     RPY_EXTERN
-    void   cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
     unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int 
nargs, void* args);
     RPY_EXTERN
-    char   cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
-    short  cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
-    int    cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
-    long   cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
     long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int 
nargs, void* args);
     RPY_EXTERN
-    float  cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
     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
-    void*  cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
+    void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args);
     RPY_EXTERN
-    char*  cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args, size_t* length);
-
+    char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, 
void* args, size_t* length);
     RPY_EXTERN
     cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t 
klass, int nargs, void* args);
     RPY_EXTERN
+    void cppyy_destructor(cppyy_type_t type, cppyy_object_t self);
+    RPY_EXTERN
     cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, 
int nargs, void* args, cppyy_type_t result_type);
 
     RPY_EXTERN
-    cppyy_funcaddr_t cppyy_get_function_address(cppyy_scope_t scope, 
cppyy_index_t idx);
+    cppyy_funcaddr_t cppyy_function_address_from_index(cppyy_scope_t scope, 
cppyy_index_t idx);
+    RPY_EXTERN
+    cppyy_funcaddr_t cppyy_function_address_from_method(cppyy_method_t method);
 
     /* handling of function argument buffer 
----------------------------------- */
     RPY_EXTERN
-    void*  cppyy_allocate_function_args(int nargs);
+    void* cppyy_allocate_function_args(int nargs);
     RPY_EXTERN
-    void   cppyy_deallocate_function_args(void* args);
+    void cppyy_deallocate_function_args(void* args);
     RPY_EXTERN
     size_t cppyy_function_arg_sizeof();
     RPY_EXTERN
@@ -92,6 +100,9 @@
     RPY_EXTERN
     int cppyy_is_enum(const char* type_name);
 
+    RPY_EXTERN
+    const char** cppyy_get_all_cpp_names(cppyy_scope_t scope, size_t* count);
+
     /* class reflection information 
------------------------------------------- */
     RPY_EXTERN
     char* cppyy_final_name(cppyy_type_t type);
@@ -105,6 +116,10 @@
     char* cppyy_base_name(cppyy_type_t type, int base_index);
     RPY_EXTERN
     int cppyy_is_subtype(cppyy_type_t derived, cppyy_type_t base);
+    RPY_EXTERN
+    int cppyy_smartptr_info(const char* name, cppyy_type_t* raw, 
cppyy_method_t* deref);
+    RPY_EXTERN
+    void cppyy_add_smartptr_type(const char* type_name);
 
     /* calculate offsets between declared and actual type, up-cast: direction 
> 0; down-cast: direction < 0 */
     RPY_EXTERN
@@ -114,8 +129,6 @@
     RPY_EXTERN
     int cppyy_num_methods(cppyy_scope_t scope);
     RPY_EXTERN
-    cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth);
-    RPY_EXTERN
     cppyy_index_t* cppyy_method_indices_from_name(cppyy_scope_t scope, const 
char* name);
 
     RPY_EXTERN
@@ -136,8 +149,12 @@
     char* cppyy_method_signature(cppyy_scope_t scope, cppyy_index_t idx, int 
show_formalargs);
     RPY_EXTERN
     char* cppyy_method_prototype(cppyy_scope_t scope, cppyy_index_t idx, int 
show_formalargs);
+    RPY_EXTERN
+    int cppyy_is_const_method(cppyy_method_t);
 
     RPY_EXTERN
+    int cppyy_exists_method_template(cppyy_scope_t scope, const char* name);
+    RPY_EXTERN
     int cppyy_method_is_template(cppyy_scope_t scope, cppyy_index_t idx);
     RPY_EXTERN
     int cppyy_method_num_template_args(cppyy_scope_t scope, cppyy_index_t idx);
@@ -169,15 +186,20 @@
     char* cppyy_datamember_type(cppyy_scope_t scope, int datamember_index);
     RPY_EXTERN
     ptrdiff_t cppyy_datamember_offset(cppyy_scope_t scope, int 
datamember_index);
-
     RPY_EXTERN
     int cppyy_datamember_index(cppyy_scope_t scope, const char* name);
 
     /* data member properties 
------------------------------------------------- */
     RPY_EXTERN
-    int cppyy_is_publicdata(cppyy_type_t type, int datamember_index);
+    int cppyy_is_publicdata(cppyy_type_t type, cppyy_index_t datamember_index);
     RPY_EXTERN
-    int cppyy_is_staticdata(cppyy_type_t type, int datamember_index);
+    int cppyy_is_staticdata(cppyy_type_t type, cppyy_index_t datamember_index);
+    RPY_EXTERN
+    int cppyy_is_const_data(cppyy_scope_t scope, cppyy_index_t idata);
+    RPY_EXTERN
+    int cppyy_is_enum_data(cppyy_scope_t scope, cppyy_index_t idata);
+    RPY_EXTERN
+    int cppyy_get_dimension_size(cppyy_scope_t scope, cppyy_index_t idata, int 
dimension);
 
     /* misc helpers 
----------------------------------------------------------- */
     RPY_EXTERN
@@ -197,7 +219,7 @@
     RPY_EXTERN
     const char* cppyy_stdvector_valuetype(const char* clname);
     RPY_EXTERN
-    size_t cppyy_stdvector_valuesize(const char* clname);
+    size_t      cppyy_stdvector_valuesize(const char* clname);
 
 #ifdef __cplusplus
 }
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
@@ -19,6 +19,9 @@
 INSTANCE_FLAGS_IS_REF      = 0x0002
 INSTANCE_FLAGS_IS_R_VALUE  = 0x0004
 
+OVERLOAD_FLAGS_USE_FFI     = 0x0001
+
+
 class FastCallNotPossible(Exception):
     pass
 
@@ -174,7 +177,7 @@
 
     @staticmethod
     def unpack_cppthis(space, w_cppinstance, declaring_scope):
-        cppinstance = space.interp_w(W_CPPClass, w_cppinstance, 
can_be_None=False)
+        cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=False)
         cppinstance._nullcheck()
         return cppinstance.get_cppthis(declaring_scope)
 
@@ -186,7 +189,7 @@
         return rffi.cast(rffi.VOIDP, loc_idx)
 
     @jit.unroll_safe
-    def call(self, cppthis, args_w):
+    def call(self, cppthis, args_w, useffi):
         jit.promote(self)
 
         assert lltype.typeOf(cppthis) == capi.C_OBJECT
@@ -218,16 +221,23 @@
 
         try:
             # attempt to call directly through ffi chain
-            if self._funcaddr:
+            if useffi and self._funcaddr:
                 try:
                     return self.do_fast_call(cppthis, args_w, call_local)
                 except FastCallNotPossible:
                     pass      # can happen if converters or executor does not 
implement ffi
 
             # ffi chain must have failed; using stub functions instead
-            args = self.prepare_arguments(args_w, call_local)
+            args, stat = self.prepare_arguments(args_w, call_local)
             try:
-                return self.executor.execute(self.space, self.cppmethod, 
cppthis, len(args_w), args)
+                result = self.executor.execute(
+                    self.space, self.cppmethod, cppthis, len(args_w), args)
+                if stat[0] != rffi.cast(rffi.ULONG, 0):
+                    what = rffi.cast(rffi.CCHARP, stat[1])
+                    pywhat = rffi.charp2str(what)
+                    capi.c_free(self.space, rffi.cast(rffi.VOIDP, what))
+                    raise OperationError(self.space.w_Exception, 
self.space.newtext(pywhat))
+                return result
             finally:
                 self.finalize_call(args, args_w, call_local)
         finally:
@@ -322,7 +332,7 @@
         # Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
         # has been offset to the matching class. Hence, the libffi pointer is
         # uniquely defined and needs to be setup only once.
-        funcaddr = capi.c_get_function_address(self.space, self.scope, 
self.index)
+        funcaddr = capi.c_function_address_from_index(self.space, self.scope, 
self.index)
         if funcaddr and cppthis:      # methods only for now
             state = self.space.fromcache(ffitypes.State)
 
@@ -373,7 +383,10 @@
                     conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, 
arg_j), loc_j)
                 capi.c_deallocate_function_args(self.space, args)
                 raise
-        return args
+        stat = rffi.cast(rffi.ULONGP,
+            lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), 
int(len(args_w))*stride))
+        stat[0] = rffi.cast(rffi.ULONG, 0)
+        return args, stat
 
     @jit.unroll_safe
     def finalize_call(self, args, args_w, call_local):
@@ -435,7 +448,7 @@
         # TODO: might have to specialize for CPPTemplatedCall on 
CPPMethod/CPPFunction here
         CPPMethod.__init__(self, space, declaring_scope, method_index, 
arg_defs, args_required)
 
-    def call(self, cppthis, args_w):
+    def call(self, cppthis, args_w, useffi):
         assert lltype.typeOf(cppthis) == capi.C_OBJECT
         for i in range(len(args_w)):
             try:
@@ -447,10 +460,10 @@
                 raise oefmt(self.space.w_TypeError,
                             "non-matching template (got %s where %s expected)",
                             s, self.templ_args[i])
-        return W_CPPBoundMethod(cppthis, self)
+        return W_CPPBoundMethod(cppthis, self, useffi)
 
-    def bound_call(self, cppthis, args_w):
-        return CPPMethod.call(self, cppthis, args_w)
+    def bound_call(self, cppthis, args_w, useffi):
+        return CPPMethod.call(self, cppthis, args_w, useffi)
 
     def __repr__(self):
         return "CPPTemplatedCall: %s" % self.prototype()
@@ -468,11 +481,11 @@
     def unpack_cppthis(space, w_cppinstance, declaring_scope):
         return rffi.cast(capi.C_OBJECT, declaring_scope.handle)
 
-    def call(self, cppthis, args_w):
+    def call(self, cppthis, args_w, useffi):
         # Note: this does not return a wrapped instance, just a pointer to the
         # new instance; the overload must still wrap it before returning. Also,
         # cppthis is declaring_scope.handle (as per unpack_cppthis(), above).
-        return CPPMethod.call(self, cppthis, args_w)
+        return CPPMethod.call(self, cppthis, args_w, useffi)
 
     def __repr__(self):
         return "CPPConstructor: %s" % self.prototype()
@@ -485,7 +498,7 @@
 
     _immutable_ = True
 
-    def call(self, cppthis, args_w):
+    def call(self, cppthis, args_w, useffi):
         end = len(args_w)-1
         if 0 <= end:
             w_item = args_w[end]
@@ -493,7 +506,7 @@
             if self.converters is None:
                 self._setup(cppthis)
             self.executor.set_item(self.space, w_item) # TODO: what about 
threads?
-        CPPMethod.call(self, cppthis, args_w)
+        CPPMethod.call(self, cppthis, args_w, useffi)
 
 
 class W_CPPOverload(W_Root):
@@ -501,7 +514,7 @@
     collection of (possibly) overloaded methods or functions. It calls these
     in order and deals with error handling and reporting."""
 
-    _attrs_ = ['space', 'scope', 'functions']
+    _attrs_ = ['space', 'scope', 'functions', 'flags']
     _immutable_fields_ = ['scope', 'functions[*]']
 
     def __init__(self, space, declaring_scope, functions):
@@ -510,6 +523,19 @@
         assert len(functions)
         from rpython.rlib import debug
         self.functions = debug.make_sure_not_resized(functions)
+        self.flags = 0
+        self.flags |= OVERLOAD_FLAGS_USE_FFI
+
+    # allow user to determine ffi use rules per overload
+    def fget_useffi(self, space):
+        return space.newbool(bool(self.flags & OVERLOAD_FLAGS_USE_FFI))
+
+    @unwrap_spec(value=bool)
+    def fset_useffi(self, space, value):
+        if space.is_true(value):
+            self.flags |= OVERLOAD_FLAGS_USE_FFI
+        else:
+            self.flags &= ~OVERLOAD_FLAGS_USE_FFI
 
     @jit.elidable_promote()
     def is_static(self):
@@ -540,7 +566,7 @@
         for i in range(len(self.functions)):
             cppyyfunc = self.functions[i]
             try:
-                return cppyyfunc.call(cppthis, args_w)
+                return cppyyfunc.call(cppthis, args_w, self.flags & 
OVERLOAD_FLAGS_USE_FFI)
             except Exception:
                 pass
 
@@ -553,7 +579,7 @@
         for i in range(len(self.functions)):
             cppyyfunc = self.functions[i]
             try:
-                return cppyyfunc.call(cppthis, args_w)
+                return cppyyfunc.call(cppthis, args_w, self.flags & 
OVERLOAD_FLAGS_USE_FFI)
             except OperationError as e:
                 # special case if there's just one function, to prevent 
clogging the error message
                 if len(self.functions) == 1:
@@ -588,6 +614,7 @@
     'CPPOverload',
     is_static = interp2app(W_CPPOverload.is_static),
     call = interp2app(W_CPPOverload.call),
+    __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, 
W_CPPOverload.fset_useffi),
     prototype = interp2app(W_CPPOverload.prototype),
 )
 
@@ -611,7 +638,7 @@
                         self.scope.name)
         w_result = W_CPPOverload.call(self, w_cppinstance, args_w)
         newthis = rffi.cast(capi.C_OBJECT, self.space.uint_w(w_result))
-        cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, 
can_be_None=True)
+        cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=True)
         if cppinstance is not None:
             cppinstance._rawobject = newthis
             memory_regulator.register(cppinstance)
@@ -642,17 +669,18 @@
 
 
 class W_CPPBoundMethod(W_Root):
-    _attrs_ = ['cppthis', 'method']
+    _attrs_ = ['cppthis', 'method', 'useffi']
 
-    def __init__(self, cppthis, method):
+    def __init__(self, cppthis, method, useffi):
         self.cppthis = cppthis
         self.method = method
+        self.useffi = useffi
 
     def __call__(self, args_w):
-        return self.method.bound_call(self.cppthis, args_w)
+        return self.method.bound_call(self.cppthis, args_w, self.useffi)
 
     def __repr__(self):
-        return "W_CPPBoundMethod(%s)" % [f.prototype() for f in self.functions]
+        return "W_CPPBoundMethod(%s)" % self.method.prototype()
 
 W_CPPBoundMethod.typedef = TypeDef(
     'CPPBoundMethod',
@@ -682,7 +710,7 @@
         return offset
 
     def get(self, w_cppinstance, w_pycppclass):
-        cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, 
can_be_None=True)
+        cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=True)
         if not cppinstance:
             raise oefmt(self.space.w_AttributeError,
                         "attribute access requires an instance")
@@ -690,7 +718,7 @@
         return self.converter.from_memory(self.space, w_cppinstance, 
w_pycppclass, offset)
 
     def set(self, w_cppinstance, w_value):
-        cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, 
can_be_None=True)
+        cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=True)
         if not cppinstance:
             raise oefmt(self.space.w_AttributeError,
                         "attribute access requires an instance")
@@ -845,24 +873,11 @@
         return self.space.w_True
 
     def ns__dir__(self):
-        # Collect a list of everything (currently) available in the namespace.
-        # The backend can filter by returning empty strings. Special care is
-        # taken for functions, which need not be unique (overloading).
-        alldir = []
-        for i in range(capi.c_num_scopes(self.space, self)):
-            sname = capi.c_scope_name(self.space, self, i)
-            if sname: alldir.append(self.space.newtext(sname))
-        allmeth = {}
-        for i in range(capi.c_num_methods(self.space, self)):
-            idx = capi.c_method_index_at(self.space, self, i)
-            mname = capi.c_method_name(self.space, self, idx)
-            if mname: allmeth.setdefault(mname, 0)
-        for m in allmeth.keys():
-            alldir.append(self.space.newtext(m))
-        for i in range(capi.c_num_datamembers(self.space, self)):
-            dname = capi.c_datamember_name(self.space, self, i)
-            if dname: alldir.append(self.space.newtext(dname))
-        return self.space.newlist(alldir)
+        alldir = capi.c_get_all_cpp_names(self.space, self)
+        w_alldir = self.space.newlist([])
+        for name in alldir:
+            w_alldir.append(self.space.newtext(name))
+        return w_alldir
         
     def missing_attribute_error(self, name):
         return oefmt(self.space.w_AttributeError,
@@ -890,8 +905,7 @@
     def _build_methods(self):
         assert len(self.methods) == 0
         methods_temp = {}
-        for i in range(capi.c_num_methods(self.space, self)):
-            idx = capi.c_method_index_at(self.space, self, i)
+        for idx in range(capi.c_num_methods(self.space, self)):
             if capi.c_is_constructor(self.space, self, idx):
                 pyname = '__init__'
             else:
@@ -1029,7 +1043,7 @@
 W_CPPComplexClassDecl.typedef.acceptable_as_base_class = False
 
 
-class W_CPPClass(W_Root):
+class W_CPPInstance(W_Root):
     _attrs_ = ['space', 'clsdecl', '_rawobject', 'flags',
                'finalizer_registered']
     _immutable_fields_ = ['clsdecl']
@@ -1109,8 +1123,8 @@
         # find a global overload in gbl, in __gnu_cxx (for iterators), or in 
the
         # scopes of the argument classes (TODO: implement that last option)
         try:
-            # TODO: expecting w_other to be an W_CPPClass is too limiting
-            other = self.space.interp_w(W_CPPClass, w_other, can_be_None=False)
+            # TODO: expecting w_other to be an W_CPPInstance is too limiting
+            other = self.space.interp_w(W_CPPInstance, w_other, 
can_be_None=False)
             for name in ["", "__gnu_cxx", "__1"]:
                 nss = scope_byname(self.space, name)
                 meth_idx = capi.c_get_global_operator(
@@ -1132,7 +1146,7 @@
 
         # fallback 2: direct pointer comparison (the class comparison is 
needed since
         # the first data member in a struct and the struct have the same 
address)
-        other = self.space.interp_w(W_CPPClass, w_other, can_be_None=False)  # 
TODO: factor out
+        other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False) 
 # TODO: factor out
         iseq = (self._rawobject == other._rawobject) and (self.clsdecl == 
other.clsdecl)
         return self.space.newbool(iseq)
 
@@ -1176,19 +1190,19 @@
         if self.flags & INSTANCE_FLAGS_PYTHON_OWNS:
             self.destruct()
 
-W_CPPClass.typedef = TypeDef(
-    'CPPClass',
-    __python_owns__ = GetSetProperty(W_CPPClass.fget_python_owns, 
W_CPPClass.fset_python_owns),
-    __init__ = interp2app(W_CPPClass.instance__init__),
-    __eq__ = interp2app(W_CPPClass.instance__eq__),
-    __ne__ = interp2app(W_CPPClass.instance__ne__),
-    __nonzero__ = interp2app(W_CPPClass.instance__nonzero__),
-    __len__ = interp2app(W_CPPClass.instance__len__),
-    __cmp__ = interp2app(W_CPPClass.instance__cmp__),
-    __repr__ = interp2app(W_CPPClass.instance__repr__),
-    __destruct__ = interp2app(W_CPPClass.destruct),
+W_CPPInstance.typedef = TypeDef(
+    'CPPInstance',
+    __python_owns__ = GetSetProperty(W_CPPInstance.fget_python_owns, 
W_CPPInstance.fset_python_owns),
+    __init__ = interp2app(W_CPPInstance.instance__init__),
+    __eq__ = interp2app(W_CPPInstance.instance__eq__),
+    __ne__ = interp2app(W_CPPInstance.instance__ne__),
+    __nonzero__ = interp2app(W_CPPInstance.instance__nonzero__),
+    __len__ = interp2app(W_CPPInstance.instance__len__),
+    __cmp__ = interp2app(W_CPPInstance.instance__cmp__),
+    __repr__ = interp2app(W_CPPInstance.instance__repr__),
+    __destruct__ = interp2app(W_CPPInstance.destruct),
 )
-W_CPPClass.typedef.acceptable_as_base_class = True
+W_CPPInstance.typedef.acceptable_as_base_class = True
 
 
 class MemoryRegulator:
@@ -1200,7 +1214,7 @@
     # Note that for now, the associated test carries an m_padding to make
     # a difference in the addresses.
     def __init__(self):
-        self.objects = rweakref.RWeakValueDictionary(int, W_CPPClass)
+        self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
 
     def register(self, obj):
         if not obj._rawobject:
@@ -1266,8 +1280,8 @@
             return obj
 
     # fresh creation
-    w_cppinstance = space.allocate_instance(W_CPPClass, w_pycppclass)
-    cppinstance = space.interp_w(W_CPPClass, w_cppinstance, can_be_None=False)
+    w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
+    cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, 
can_be_None=False)
     cppinstance.__init__(space, clsdecl, rawobject, is_ref, python_owns)
     memory_regulator.register(cppinstance)
     return w_cppinstance
@@ -1311,7 +1325,7 @@
 
 def move(space, w_obj):
     """Casts the given instance into an C++-style rvalue."""
-    obj = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
+    obj = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
     if obj:
         obj.flags |= INSTANCE_FLAGS_IS_R_VALUE
     return w_obj
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
@@ -7,7 +7,7 @@
 # Metaclasses are needed to store C++ static data members as properties. Since
 # the interp-level does not support metaclasses, they are created at app-level.
 # These are the metaclass base classes:
-class CPPMetaScope(type):
+class CPPScope(type):
     def __getattr__(self, name):
         try:
             return get_scoped_pycppitem(self, name)  # will cache on self
@@ -15,11 +15,11 @@
             raise AttributeError("%s object has no attribute '%s' (details: 
%s)" %
                                  (self, name, str(e)))
 
-class CPPMetaNamespace(CPPMetaScope):
+class CPPMetaNamespace(CPPScope):
     def __dir__(self):
         return self.__cppdecl__.__dir__()
 
-class CPPMetaClass(CPPMetaScope):
+class CPPClass(CPPScope):
     pass
 
 # namespace base class (class base class defined in _init_pythonify)
@@ -173,7 +173,7 @@
     # get a list of base classes for class creation
     bases = [get_pycppclass(base) for base in decl.get_base_names()]
     if not bases:
-        bases = [CPPClass,]
+        bases = [CPPInstance,]
     else:
         # it's possible that the required class now has been built if one of
         # the base classes uses it in e.g. a function interface
@@ -214,7 +214,7 @@
 
     # create a metaclass to allow properties (for static data write access)
     metabases = [type(base) for base in bases]
-    metacpp = type(CPPMetaScope)(cl_name+'_meta', _drop_cycles(metabases), 
d_meta)
+    metacpp = type(CPPScope)(cl_name+'_meta', _drop_cycles(metabases), d_meta)
 
     # create the python-side C++ class
     pycls = metacpp(cl_name, _drop_cycles(bases), d_class)
@@ -412,11 +412,11 @@
     # at pypy-c startup, rather than on the "import _cppyy" statement
     import _cppyy
 
-    # root of all proxy classes: CPPClass in pythonify exists to combine the
-    # CPPMetaScope metaclass with the interp-level CPPClassBase
-    global CPPClass
-    class CPPClass(_cppyy.CPPClassBase):
-        __metaclass__ = CPPMetaScope
+    # root of all proxy classes: CPPInstance in pythonify exists to combine
+    # the CPPScope metaclass with the interp-level CPPInstanceBase
+    global CPPInstance
+    class CPPInstance(_cppyy.CPPInstanceBase):
+        __metaclass__ = CPPScope
         pass
 
     # class generator callback
@@ -438,9 +438,8 @@
     gbl.std.move = _cppyy.move
 
     # install a type for enums to refer to
-    # TODO: this is correct for C++98, not for C++11 and in general there will
-    # be the same issue for all typedef'd builtin types
     setattr(gbl, 'internal_enum_type_t', int)
+    setattr(gbl, 'unsigned int',         int)     # if resolved
 
     # install for user access
     _cppyy.gbl = gbl
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
@@ -407,11 +407,9 @@
 
 
 /* name to opaque C++ scope representation -------------------------------- */
-int cppyy_num_scopes(cppyy_scope_t handle) {
-    return 0;
-}
-
 char* cppyy_resolve_name(const char* cppitem_name) {
+    if (cppyy_is_enum(cppitem_name))
+        return cppstring_to_cstring("internal_enum_type_t");
     return cppstring_to_cstring(cppitem_name);
 }
 
@@ -851,10 +849,13 @@
     return (cppyy_object_t)result;
 }
 
-cppyy_funcaddr_t cppyy_get_function_address(cppyy_scope_t /* scope */, 
cppyy_index_t /* idx */) {
+cppyy_funcaddr_t cppyy_function_address_from_index(cppyy_scope_t /* scope */, 
cppyy_index_t /* idx */) {
     return (cppyy_funcaddr_t)0;
 }
 
+cppyy_funcaddr_t cppyy_function_address_from_method(cppyy_method_t /* method 
*/) {
+    return (cppyy_funcaddr_t)0;
+}
 
 /* handling of function argument buffer ----------------------------------- */
 void* cppyy_allocate_function_args(int nargs) {
@@ -926,10 +927,6 @@
     return s_scopes[handle].m_methods.size();
 }
 
-cppyy_index_t cppyy_method_index_at(cppyy_scope_t /* scope */, int imeth) {
-    return (cppyy_index_t)imeth;
-}
-
 char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t method_index) {
     return 
cppstring_to_cstring(s_scopes[handle].m_methods[(int)method_index].m_name);
 }
@@ -978,8 +975,17 @@
     return (cppyy_method_t)0;
 }
 
+cppyy_index_t cppyy_get_global_operator(cppyy_scope_t /* scope */,
+        cppyy_scope_t /* lc */, cppyy_scope_t /* rc */, const char* /* op */) {
+    return (cppyy_index_t)-1;
+}
+
 
 /* method properties -----------------------------------------------------  */
+int cppyy_is_publicmethod(cppyy_type_t /* handle */, cppyy_index_t /* 
method_index */) {
+    return 1;
+}
+
 int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
     if (s_scopes.find(handle) != s_scopes.end())
         return s_scopes[handle].m_methods[method_index].m_type == kConstructor;
@@ -987,6 +993,10 @@
     return 0;
 }
 
+int cppyy_is_destructor(cppyy_type_t /* handle */, cppyy_index_t /* 
method_index */) {
+    return 0;
+}
+
 int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
     if (s_scopes.find(handle) != s_scopes.end())
         return s_scopes[handle].m_methods[method_index].m_type == kStatic;
@@ -1014,14 +1024,22 @@
 
 
 /* data member properties ------------------------------------------------  */
-int cppyy_is_publicdata(cppyy_scope_t handle, int idatambr) {
+int cppyy_is_publicdata(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr 
*/) {
     return 1;
 }
 
-int cppyy_is_staticdata(cppyy_scope_t handle, int idatambr) {
+int cppyy_is_staticdata(cppyy_scope_t handle, cppyy_index_t idatambr) {
     return s_scopes[handle].m_datambrs[idatambr].m_isstatic;
 }
 
+int cppyy_is_const_data(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr 
*/) {
+    return 0;
+}
+
+int cppyy_is_enum_data(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr 
*/) {
+    return 0;
+}
+
 
 /* misc helpers ----------------------------------------------------------- */
 #if defined(_MSC_VER)
diff --git a/pypy/module/_cppyy/test/Makefile b/pypy/module/_cppyy/test/Makefile
--- a/pypy/module/_cppyy/test/Makefile
+++ b/pypy/module/_cppyy/test/Makefile
@@ -14,7 +14,7 @@
 
 HASGENREFLEX:=$(shell command -v genreflex 2> /dev/null)
 
-cppflags=-std=c++11 -O3 -m64 -fPIC -rdynamic
+cppflags=-std=c++14 -O3 -m64 -fPIC -rdynamic
 ifdef HASGENREFLEX
   genreflex_flags:=$(shell genreflex --cppflags)
   cppflags+=$(genreflex_flags)
diff --git a/pypy/module/_cppyy/test/advancedcpp.cxx 
b/pypy/module/_cppyy/test/advancedcpp.cxx
--- a/pypy/module/_cppyy/test/advancedcpp.cxx
+++ b/pypy/module/_cppyy/test/advancedcpp.cxx
@@ -1,5 +1,7 @@
 #include "advancedcpp.h"
 
+#include <stdexcept>
+
 
 // for testing of default arguments
 #define IMPLEMENT_DEFAULTER_CLASS(type, tname)                               \
@@ -112,3 +114,13 @@
 
 std::string overload_the_other_way::gime() { return "aap"; }
 int overload_the_other_way::gime() const { return 1; }
+
+
+// exception handling testing
+void Thrower::throw_anything() {
+    throw 1;
+}
+
+void Thrower::throw_exception() {
+    throw std::runtime_error("C++ function failed");
+}
diff --git a/pypy/module/_cppyy/test/advancedcpp.h 
b/pypy/module/_cppyy/test/advancedcpp.h
--- a/pypy/module/_cppyy/test/advancedcpp.h
+++ b/pypy/module/_cppyy/test/advancedcpp.h
@@ -59,7 +59,7 @@
 class a_class {                    // for esoteric inheritance testing
 public:
     a_class() { m_a = 1; m_da = 1.1; }
-    ~a_class() {}
+    virtual ~a_class() {}
     virtual int get_value() = 0;
 
 public:
@@ -221,6 +221,7 @@
 //===========================================================================
 class some_abstract_class {        // to test abstract class handling
 public:
+    virtual ~some_abstract_class() {}
     virtual void a_virtual_method() = 0;
 };
 
@@ -399,3 +400,11 @@
    std::string gime();
    int gime() const;
 };
+
+
+//===========================================================================
+class Thrower {                    // exception handling testing
+public:
+    void throw_anything();
+    void throw_exception();
+};
diff --git a/pypy/module/_cppyy/test/advancedcpp.xml 
b/pypy/module/_cppyy/test/advancedcpp.xml
--- a/pypy/module/_cppyy/test/advancedcpp.xml
+++ b/pypy/module/_cppyy/test/advancedcpp.xml
@@ -57,4 +57,6 @@
   <class name="overload_one_way" />
   <class name="overload_the_other_way" />
 
+  <class name="Thrower" />
+
 </lcgdict>
diff --git a/pypy/module/_cppyy/test/conftest.py 
b/pypy/module/_cppyy/test/conftest.py
--- a/pypy/module/_cppyy/test/conftest.py
+++ b/pypy/module/_cppyy/test/conftest.py
@@ -55,7 +55,7 @@
                 separate_module_files=[srcpath.join('dummy_backend.cxx')],
                 include_dirs=[incpath, tstpath, cdir],
                 compile_extra=['-DRPY_EXTERN=RPY_EXPORTED', 
'-DCPPYY_DUMMY_BACKEND',
-                               '-fno-strict-aliasing', '-std=c++11'],
+                               '-fno-strict-aliasing', '-std=c++14'],
                 use_cpp_linker=True,
             )
 
@@ -65,7 +65,7 @@
                     outputfilename='libcppyy_dummy_backend',
                     standalone=False)
             except CompilationError as e:
-                if '-std=c++11' in str(e):
+                if '-std=c++14' in str(e):
                     global disabled
                     disabled = str(e)
                     return
diff --git a/pypy/module/_cppyy/test/fragile.h 
b/pypy/module/_cppyy/test/fragile.h
--- a/pypy/module/_cppyy/test/fragile.h
+++ b/pypy/module/_cppyy/test/fragile.h
@@ -30,6 +30,7 @@
     void overload(int, no_such_class* p = 0) {}
 };
 
+
 static const int dummy_location = 0xdead;
 
 class E {
@@ -105,6 +106,7 @@
 
 class M {
 public:
+    virtual ~M() {}
     enum E1 { kOnce=42 };
     enum E2 { kTwice=12 };
 };
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
@@ -656,3 +656,22 @@
         # TODO: currently fails b/c double** not understood as &double*
         #assert cppyy.gbl.my_global_ptr[0] == 1234.
 
+    def test22_exceptions(self):
+        """Catching of C++ exceptions"""
+
+        import _cppyy as cppyy
+        Thrower = cppyy.gbl.Thrower
+
+        # TODO: clean up this interface:
+        Thrower.__cppdecl__.get_overload('throw_anything').__useffi__  = False
+        Thrower.__cppdecl__.get_overload('throw_exception').__useffi__ = False
+
+        t = Thrower()
+
+        assert raises(Exception, t.throw_anything)
+        assert raises(Exception, t.throw_exception)
+
+        try:
+            t.throw_exception()
+        except Exception, e:
+            "C++ function failed" in str(e)
diff --git a/pypy/module/_cppyy/test/test_overloads.py 
b/pypy/module/_cppyy/test/test_overloads.py
--- a/pypy/module/_cppyy/test/test_overloads.py
+++ b/pypy/module/_cppyy/test/test_overloads.py
@@ -15,7 +15,6 @@
     spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
 
     def setup_class(cls):
-        env = os.environ
         cls.w_test_dct  = cls.space.newtext(test_dct)
         cls.w_overloads = cls.space.appexec([], """():
             import ctypes
diff --git a/pypy/module/_cppyy/test/test_zjit.py 
b/pypy/module/_cppyy/test/test_zjit.py
--- a/pypy/module/_cppyy/test/test_zjit.py
+++ b/pypy/module/_cppyy/test/test_zjit.py
@@ -137,6 +137,7 @@
         executor.get_executor(self, 'int').__class__.c_stubcall = 
staticmethod(c_call_i)
 
         self.w_AttributeError      = FakeException(self, "AttributeError")
+        self.w_Exception           = FakeException(self, "Exception")
         self.w_KeyError            = FakeException(self, "KeyError")
         self.w_NotImplementedError = FakeException(self, "NotImplementedError")
         self.w_ReferenceError      = FakeException(self, "ReferenceError")
@@ -282,7 +283,7 @@
             inst = interp_cppyy._bind_object(space, FakeInt(0), cls, True)
             cls.get_overload("__init__").call(inst, [FakeInt(0)])
             cppmethod = cls.get_overload(method_name)
-            assert isinstance(inst, interp_cppyy.W_CPPClass)
+            assert isinstance(inst, interp_cppyy.W_CPPInstance)
             i = 10
             while i > 0:
                 drv.jit_merge_point(inst=inst, cppmethod=cppmethod, i=i)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to