[pypy-commit] pypy ffi-backend: hg merge default

arigo noreply at buildbot.pypy.org
Wed Aug 1 17:30:17 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r56527:fac9454da01e
Date: 2012-08-01 17:29 +0200
http://bitbucket.org/pypy/pypy/changeset/fac9454da01e/

Log:	hg merge default

diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -153,6 +153,7 @@
 
 Automatic class loader
 ======================
+
 There is one big problem in the code above, that prevents its use in a (large
 scale) production setting: the explicit loading of the reflection library.
 Clearly, if explicit load statements such as these show up in code downstream
@@ -164,7 +165,9 @@
 The class loader makes use of so-called rootmap files, which ``genreflex``
 can produce.
 These files contain the list of available C++ classes and specify the library
-that needs to be loaded for their use.
+that needs to be loaded for their use (as an aside, this listing allows for a
+cross-check to see whether reflection info is generated for all classes that
+you expect).
 By convention, the rootmap files should be located next to the reflection info
 libraries, so that they can be found through the normal shared library search
 path.
@@ -198,6 +201,7 @@
 
 Advanced example
 ================
+
 The following snippet of C++ is very contrived, to allow showing that such
 pathological code can be handled and to show how certain features play out in
 practice::
@@ -253,6 +257,9 @@
 With the aid of a selection file, a large project can be easily managed:
 simply ``#include`` all relevant headers into a single header file that is
 handed to ``genreflex``.
+In fact, if you hand multiple header files to ``genreflex``, then a selection
+file is almost obligatory: without it, only classes from the last header will
+be selected.
 Then, apply a selection file to pick up all the relevant classes.
 For our purposes, the following rather straightforward selection will do
 (the name ``lcgdict`` for the root is historical, but required)::
@@ -325,15 +332,43 @@
 (active memory management is one such case), but by and large, if the use of a
 feature does not strike you as obvious, it is more likely to simply be a bug.
 That is a strong statement to make, but also a worthy goal.
+For the C++ side of the examples, refer to this `example code`_, which was
+bound using::
+
+    $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so
+    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex
+
+.. _`example code`: cppyy_example.html
 
 * **abstract classes**: Are represented as python classes, since they are
   needed to complete the inheritance hierarchies, but will raise an exception
   if an attempt is made to instantiate from them.
+  Example::
+
+    >>>> from cppyy.gbl import AbstractClass, ConcreteClass
+    >>>> a = AbstractClass()
+    Traceback (most recent call last):
+      File "<console>", line 1, in <module>
+    TypeError: cannot instantiate abstract class 'AbstractClass'
+    >>>> issubclass(ConcreteClass, AbstractClass)
+    True
+    >>>> c = ConcreteClass()
+    >>>> isinstance(c, AbstractClass)
+    True
+    >>>>
 
 * **arrays**: Supported for builtin data types only, as used from module
   ``array``.
   Out-of-bounds checking is limited to those cases where the size is known at
   compile time (and hence part of the reflection info).
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> from array import array
+    >>>> c = ConcreteClass()
+    >>>> c.array_method(array('d', [1., 2., 3., 4.]), 4)
+    1 2 3 4
+    >>>> 
 
 * **builtin data types**: Map onto the expected equivalent python types, with
   the caveat that there may be size differences, and thus it is possible that
@@ -344,23 +379,77 @@
   in the hierarchy of the object being returned.
   This is important to preserve object identity as well as to make casting,
   a pure C++ feature after all, superfluous.
+  Example::
+
+    >>>> from cppyy.gbl import AbstractClass, ConcreteClass
+    >>>> c = ConcreteClass()
+    >>>> ConcreteClass.show_autocast.__doc__
+    'AbstractClass* ConcreteClass::show_autocast()'
+    >>>> d = c.show_autocast()
+    >>>> type(d)
+    <class '__main__.ConcreteClass'>
+    >>>>
+
+  However, if need be, you can perform C++-style reinterpret_casts (i.e.
+  without taking offsets into account), by taking and rebinding the address
+  of an object::
+
+    >>>> from cppyy import addressof, bind_object
+    >>>> e = bind_object(addressof(d), AbstractClass)
+    >>>> type(e)
+    <class '__main__.AbstractClass'>
+    >>>>
 
 * **classes and structs**: Get mapped onto python classes, where they can be
   instantiated as expected.
   If classes are inner classes or live in a namespace, their naming and
   location will reflect that.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass, Namespace
+    >>>> ConcreteClass == Namespace.ConcreteClass
+    False
+    >>>> n = Namespace.ConcreteClass.NestedClass()
+    >>>> type(n)
+    <class '__main__.Namespace::ConcreteClass::NestedClass'>
+    >>>> 
 
 * **data members**: Public data members are represented as python properties
   and provide read and write access on instances as expected.
+  Private and protected data members are not accessible.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> c = ConcreteClass()
+    >>>> c.m_int
+    42
+    >>>>
 
 * **default arguments**: C++ default arguments work as expected, but python
   keywords are not supported.
   It is technically possible to support keywords, but for the C++ interface,
   the formal argument names have no meaning and are not considered part of the
   API, hence it is not a good idea to use keywords.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> c = ConcreteClass()       # uses default argument
+    >>>> c.m_int
+    42
+    >>>> c = ConcreteClass(13)
+    >>>> c.m_int
+    13
+    >>>>
 
 * **doc strings**: The doc string of a method or function contains the C++
   arguments and return types of all overloads of that name, as applicable.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> print ConcreteClass.array_method.__doc__
+    void ConcreteClass::array_method(int*, int)
+    void ConcreteClass::array_method(double*, int)
+    >>>> 
 
 * **enums**: Are translated as ints with no further checking.
 
@@ -375,11 +464,40 @@
   This is a current, not a fundamental, limitation.
   The C++ side will not see any overridden methods on the python side, as
   cross-inheritance is planned but not yet supported.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> help(ConcreteClass)
+    Help on class ConcreteClass in module __main__:
+
+    class ConcreteClass(AbstractClass)
+     |  Method resolution order:
+     |      ConcreteClass
+     |      AbstractClass
+     |      cppyy.CPPObject
+     |      __builtin__.CPPInstance
+     |      __builtin__.object
+     |  
+     |  Methods defined here:
+     |  
+     |  ConcreteClass(self, *args)
+     |      ConcreteClass::ConcreteClass(const ConcreteClass&)
+     |      ConcreteClass::ConcreteClass(int)
+     |      ConcreteClass::ConcreteClass()
+     |
+     etc. ....
 
 * **memory**: C++ instances created by calling their constructor from python
   are owned by python.
   You can check/change the ownership with the _python_owns flag that every
   bound instance carries.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> c = ConcreteClass()
+    >>>> c._python_owns            # True: object created in Python
+    True
+    >>>> 
 
 * **methods**: Are represented as python methods and work as expected.
   They are first class objects and can be bound to an instance.
@@ -395,23 +513,34 @@
   Namespaces are more open-ended than classes, so sometimes initial access may
   result in updates as data and functions are looked up and constructed
   lazily.
-  Thus the result of ``dir()`` on a namespace should not be relied upon: it
-  only shows the already accessed members. (TODO: to be fixed by implementing
-  __dir__.)
+  Thus the result of ``dir()`` on a namespace shows the classes available,
+  even if they may not have been created yet.
+  It does not show classes that could potentially be loaded by the class
+  loader.
+  Once created, namespaces are registered as modules, to allow importing from
+  them.
+  Namespace currently do not work with the class loader.
+  Fixing these bootstrap problems is on the TODO list.
   The global namespace is ``cppyy.gbl``.
 
 * **operator conversions**: If defined in the C++ class and a python
   equivalent exists (i.e. all builtin integer and floating point types, as well
   as ``bool``), it will map onto that python conversion.
   Note that ``char*`` is mapped onto ``__str__``.
+  Example::
+
+    >>>> from cppyy.gbl import ConcreteClass
+    >>>> print ConcreteClass()
+    Hello operator const char*!
+    >>>> 
 
 * **operator overloads**: If defined in the C++ class and if a python
   equivalent is available (not always the case, think e.g. of ``operator||``),
   then they work as expected.
   Special care needs to be taken for global operator overloads in C++: first,
   make sure that they are actually reflected, especially for the global
-  overloads for ``operator==`` and ``operator!=`` of STL iterators in the case
-  of gcc.
+  overloads for ``operator==`` and ``operator!=`` of STL vector iterators in
+  the case of gcc (note that they are not needed to iterator over a vector).
   Second, make sure that reflection info is loaded in the proper order.
   I.e. that these global overloads are available before use.
 
@@ -441,17 +570,30 @@
   will be returned if the return type is ``const char*``.
 
 * **templated classes**: Are represented in a meta-class style in python.
-  This looks a little bit confusing, but conceptually is rather natural.
+  This may look a little bit confusing, but conceptually is rather natural.
   For example, given the class ``std::vector<int>``, the meta-class part would
-  be ``std.vector`` in python.
+  be ``std.vector``.
   Then, to get the instantiation on ``int``, do ``std.vector(int)`` and to
-  create an instance of that class, do ``std.vector(int)()``.
+  create an instance of that class, do ``std.vector(int)()``::
+
+    >>>> import cppyy
+    >>>> cppyy.load_reflection_info('libexampleDict.so')
+    >>>> cppyy.gbl.std.vector                # template metatype
+    <cppyy.CppyyTemplateType object at 0x00007fcdd330f1a0>
+    >>>> cppyy.gbl.std.vector(int)           # instantiates template -> class
+    <class '__main__.std::vector<int>'>
+    >>>> cppyy.gbl.std.vector(int)()         # instantiates class -> object
+    <__main__.std::vector<int> object at 0x00007fe480ba4bc0>
+    >>>> 
+
   Note that templates can be build up by handing actual types to the class
   instantiation (as done in this vector example), or by passing in the list of
   template arguments as a string.
   The former is a lot easier to work with if you have template instantiations
-  using classes that themselves are templates (etc.) in the arguments.
-  All classes must already exist in the loaded reflection info.
+  using classes that themselves are templates in  the arguments (think e.g a
+  vector of vectors).
+  All template classes must already exist in the loaded reflection info, they
+  do not work (yet) with the class loader.
 
 * **typedefs**: Are simple python references to the actual classes to which
   they refer.
@@ -502,11 +644,19 @@
 
 If you know for certain that all symbols will be linked in from other sources,
 you can also declare the explicit template instantiation ``extern``.
+An alternative is to add an object to an unnamed namespace::
 
-Unfortunately, this is not enough for gcc.
-The iterators, if they are going to be used, need to be instantiated as well,
-as do the comparison operators on those iterators, as these live in an
-internal namespace, rather than in the iterator classes.
+    namespace {
+        std::vector<MyClass> vmc;
+    } // unnamed namespace
+
+Unfortunately, this is not always enough for gcc.
+The iterators of vectors, if they are going to be used, need to be
+instantiated as well, as do the comparison operators on those iterators, as
+these live in an internal namespace, rather than in the iterator classes.
+Note that you do NOT need this iterators to iterator over a vector.
+You only need them if you plan to explicitly call e.g. ``begin`` and ``end``
+methods, and do comparisons of iterators.
 One way to handle this, is to deal with this once in a macro, then reuse that
 macro for all ``vector`` classes.
 Thus, the header above needs this (again protected with
@@ -533,8 +683,6 @@
     <lcgdict>
         <class pattern="std::vector<*>" />
         <class pattern="std::vector<*>::iterator" />
-        <class pattern="std::_Vector_base<*>" />
-        <class pattern="std::_Vector_base<*>::_Vector_impl" />
         <function name="__gnu_cxx::operator=="/>
         <function name="__gnu_cxx::operator!="/>
 
@@ -549,7 +697,7 @@
 Note: this is a dirty corner that clearly could do with some automation,
 even if the macro already helps.
 Such automation is planned.
-In fact, in the cling world, the backend can perform the template
+In fact, in the Cling world, the backend can perform the template
 instantations and generate the reflection info on the fly, and none of the
 above will any longer be necessary.
 
@@ -568,7 +716,8 @@
     1 2 3
     >>>>
 
-Other templates work similarly.
+Other templates work similarly, but are typically simpler, as there are no
+similar issues with iterators for e.g. ``std::list``.
 The arguments to the template instantiation can either be a string with the
 full list of arguments, or the explicit classes.
 The latter makes for easier code writing if the classes passed to the
@@ -655,3 +804,15 @@
 In that wrapper script you can rename methods exactly the way you need it.
 
 In the cling world, all these differences will be resolved.
+
+
+Python3
+=======
+
+To change versions of CPython (to Python3, another version of Python, or later
+to the `Py3k`_ version of PyPy), the only part that requires recompilation is
+the bindings module, be it ``cppyy`` or ``libPyROOT.so`` (in PyCintex).
+Although ``genreflex`` is indeed a Python tool, the generated reflection
+information is completely independent of Python.
+
+.. _`Py3k`: https://bitbucket.org/pypy/pypy/src/py3k
diff --git a/pypy/doc/cppyy_example.rst b/pypy/doc/cppyy_example.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/cppyy_example.rst
@@ -0,0 +1,56 @@
+// File: example.h::
+
+    #include <iostream>
+    #include <vector>
+
+    class AbstractClass {
+    public:
+        virtual ~AbstractClass() {}
+        virtual void abstract_method() = 0;
+    };
+
+    class ConcreteClass : AbstractClass {
+    public:
+        ConcreteClass(int n=42) : m_int(n) {}
+        ~ConcreteClass() {}
+
+        virtual void abstract_method() {
+            std::cout << "called concrete method" << std::endl;
+        }
+
+        void array_method(int* ad, int size) {
+            for (int i=0; i < size; ++i)
+                std::cout << ad[i] << ' ';
+            std::cout << std::endl;
+        }
+
+        void array_method(double* ad, int size) {
+            for (int i=0; i < size; ++i)
+                std::cout << ad[i] << ' ';
+            std::cout << std::endl;
+        }
+
+        AbstractClass* show_autocast() {
+            return this;
+        }
+
+        operator const char*() {
+            return "Hello operator const char*!";
+        }
+
+    public:
+        int m_int;
+    };
+
+    namespace Namespace {
+
+       class ConcreteClass {
+       public:
+          class NestedClass {
+          public:
+             std::vector<int> m_v;
+          };
+
+       };
+
+    } // namespace Namespace
diff --git a/pypy/jit/codewriter/policy.py b/pypy/jit/codewriter/policy.py
--- a/pypy/jit/codewriter/policy.py
+++ b/pypy/jit/codewriter/policy.py
@@ -63,11 +63,10 @@
             contains_loop = contains_loop and not getattr(
                     func, '_jit_unroll_safe_', False)
 
-        unsupported = contains_unsupported_variable_type(graph,
+        res = see_function and not contains_unsupported_variable_type(graph,
                             self.supports_floats,
                             self.supports_longlong,
                             self.supports_singlefloats)
-        res = see_function and not unsupported
         if res and contains_loop:
             self.unsafe_loopy_graphs.add(graph)
         res = res and not contains_loop
diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -96,6 +96,9 @@
         block_size = rffi.getintfield(digest_type, 'c_block_size')
         return space.wrap(block_size)
 
+    def get_name(self, space):
+        return space.wrap(self.name)
+
     def _digest(self, space):
         with lltype.scoped_alloc(ropenssl.EVP_MD_CTX.TO) as ctx:
             with self.lock:
@@ -118,6 +121,7 @@
     digest_size=GetSetProperty(W_Hash.get_digest_size),
     digestsize=GetSetProperty(W_Hash.get_digest_size),
     block_size=GetSetProperty(W_Hash.get_block_size),
+    name=GetSetProperty(W_Hash.get_name),
     )
 W_Hash.acceptable_as_base_class = False
 
diff --git a/pypy/module/_hashlib/test/test_hashlib.py b/pypy/module/_hashlib/test/test_hashlib.py
--- a/pypy/module/_hashlib/test/test_hashlib.py
+++ b/pypy/module/_hashlib/test/test_hashlib.py
@@ -20,6 +20,7 @@
                                     'sha512': 64,
                                     }.items():
             h = hashlib.new(name)
+            assert h.name == name
             assert h.digest_size == expected_size
             assert h.digestsize == expected_size
             #
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
@@ -1,7 +1,9 @@
 from pypy.interpreter.mixedmodule import MixedModule
 
 class Module(MixedModule):
-    """    """
+    "This module provides runtime bindings to C++ code for which reflection\n\
+    info has been generated. Current supported back-ends are Reflex and CINT.\n\
+    See http://doc.pypy.org/en/latest/cppyy.html for full details."
 
     interpleveldefs = {
         '_load_dictionary'       : 'interp_cppyy.load_dictionary',
@@ -20,3 +22,12 @@
         'load_reflection_info'   : 'pythonify.load_reflection_info',
         'add_pythonization'      : 'pythonify.add_pythonization',
     }
+
+    def __init__(self, space, *args):
+        "NOT_RPYTHON"
+        MixedModule.__init__(self, space, *args)
+
+        # pythonization functions may be written in RPython, but the interp2app
+        # code generation is not, so give it a chance to run now
+        from pypy.module.cppyy import capi
+        capi.register_pythonizations(space)
diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -4,7 +4,10 @@
 import reflex_capi as backend
 #import cint_capi as backend
 
-identify = backend.identify
+identify  = backend.identify
+pythonize = backend.pythonize
+register_pythonizations = backend.register_pythonizations
+
 ts_reflect = backend.ts_reflect
 ts_call    = backend.ts_call
 ts_memory  = backend.ts_memory
@@ -23,6 +26,8 @@
 C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL)
 
 C_METHOD = _C_OPAQUE_PTR
+C_INDEX = rffi.LONG
+WLAVC_INDEX = rffi.LONG
 
 C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
 C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
@@ -37,6 +42,20 @@
 c_load_dictionary = backend.c_load_dictionary
 
 # name to opaque C++ scope representation ------------------------------------
+_c_num_scopes = rffi.llexternal(
+    "cppyy_num_scopes",
+    [C_SCOPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_num_scopes(cppscope):
+    return _c_num_scopes(cppscope.handle)
+_c_scope_name = rffi.llexternal(
+    "cppyy_scope_name",
+    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    compilation_info = backend.eci)
+def c_scope_name(cppscope, iscope):
+    return charp2str_free(_c_scope_name(cppscope.handle, iscope))
+
 _c_resolve_name = rffi.llexternal(
     "cppyy_resolve_name",
     [rffi.CCHARP], rffi.CCHARP,
@@ -93,7 +112,7 @@
     compilation_info=backend.eci)
 c_call_b = rffi.llexternal(
     "cppyy_call_b",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT,
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR,
     threadsafe=ts_call,
     compilation_info=backend.eci)
 c_call_c = rffi.llexternal(
@@ -123,7 +142,7 @@
     compilation_info=backend.eci)
 c_call_f = rffi.llexternal(
     "cppyy_call_f",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT,
     threadsafe=ts_call,
     compilation_info=backend.eci)
 c_call_d = rffi.llexternal(
@@ -148,23 +167,22 @@
     [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void,
     threadsafe=ts_call,
     compilation_info=backend.eci)
-
 _c_call_o = rffi.llexternal(
     "cppyy_call_o",
     [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG,
     threadsafe=ts_call,
     compilation_info=backend.eci)
-def c_call_o(method_index, cppobj, nargs, args, cppclass):
-    return _c_call_o(method_index, cppobj, nargs, args, cppclass.handle)
+def c_call_o(method, cppobj, nargs, args, cppclass):
+    return _c_call_o(method, cppobj, nargs, args, cppclass.handle)
 
 _c_get_methptr_getter = rffi.llexternal(
     "cppyy_get_methptr_getter",
-    [C_SCOPE, rffi.INT], C_METHPTRGETTER_PTR,
+    [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR,
     threadsafe=ts_reflect,
     compilation_info=backend.eci,
     elidable_function=True)
-def c_get_methptr_getter(cppscope, method_index):
-    return _c_get_methptr_getter(cppscope.handle, method_index)
+def c_get_methptr_getter(cppscope, index):
+    return _c_get_methptr_getter(cppscope.handle, index)
 
 # handling of function argument buffer ---------------------------------------
 c_allocate_function_args = rffi.llexternal(
@@ -236,7 +254,6 @@
     compilation_info=backend.eci)
 def c_base_name(cppclass, base_index):
     return charp2str_free(_c_base_name(cppclass.handle, base_index))
-
 _c_is_subtype = rffi.llexternal(
     "cppyy_is_subtype",
     [C_TYPE, C_TYPE], rffi.INT,
@@ -269,87 +286,103 @@
     compilation_info=backend.eci)
 def c_num_methods(cppscope):
     return _c_num_methods(cppscope.handle)
+_c_method_index_at = rffi.llexternal(
+    "cppyy_method_index_at",
+    [C_SCOPE, rffi.INT], C_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_index_at(cppscope, imethod):
+    return _c_method_index_at(cppscope.handle, imethod)
+_c_method_index_from_name = rffi.llexternal(
+    "cppyy_method_index_from_name",
+    [C_SCOPE, rffi.CCHARP], C_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_index_from_name(cppscope, name):
+    return _c_method_index_from_name(cppscope.handle, name)
+
 _c_method_name = rffi.llexternal(
     "cppyy_method_name",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_name(cppscope, method_index):
-    return charp2str_free(_c_method_name(cppscope.handle, method_index))
+def c_method_name(cppscope, index):
+    return charp2str_free(_c_method_name(cppscope.handle, index))
 _c_method_result_type = rffi.llexternal(
     "cppyy_method_result_type",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_result_type(cppscope, method_index):
-    return charp2str_free(_c_method_result_type(cppscope.handle, method_index))
+def c_method_result_type(cppscope, index):
+    return charp2str_free(_c_method_result_type(cppscope.handle, index))
 _c_method_num_args = rffi.llexternal(
     "cppyy_method_num_args",
-    [C_SCOPE, rffi.INT], rffi.INT,
+    [C_SCOPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_num_args(cppscope, method_index):
-    return _c_method_num_args(cppscope.handle, method_index)
+def c_method_num_args(cppscope, index):
+    return _c_method_num_args(cppscope.handle, index)
 _c_method_req_args = rffi.llexternal(
     "cppyy_method_req_args",
-    [C_SCOPE, rffi.INT], rffi.INT,
+    [C_SCOPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_req_args(cppscope, method_index):
-    return _c_method_req_args(cppscope.handle, method_index)
+def c_method_req_args(cppscope, index):
+    return _c_method_req_args(cppscope.handle, index)
 _c_method_arg_type = rffi.llexternal(
     "cppyy_method_arg_type",
-    [C_SCOPE, rffi.INT, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_arg_type(cppscope, method_index, arg_index):
-    return charp2str_free(_c_method_arg_type(cppscope.handle, method_index, arg_index))
+def c_method_arg_type(cppscope, index, arg_index):
+    return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index))
 _c_method_arg_default = rffi.llexternal(
     "cppyy_method_arg_default",
-    [C_SCOPE, rffi.INT, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_arg_default(cppscope, method_index, arg_index):
-    return charp2str_free(_c_method_arg_default(cppscope.handle, method_index, arg_index))
+def c_method_arg_default(cppscope, index, arg_index):
+    return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index))
 _c_method_signature = rffi.llexternal(
     "cppyy_method_signature",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_signature(cppscope, method_index):
-    return charp2str_free(_c_method_signature(cppscope.handle, method_index))
-
-_c_method_index = rffi.llexternal(
-    "cppyy_method_index",
-    [C_SCOPE, rffi.CCHARP], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_method_index(cppscope, name):
-    return _c_method_index(cppscope.handle, name)
+def c_method_signature(cppscope, index):
+    return charp2str_free(_c_method_signature(cppscope.handle, index))
 
 _c_get_method = rffi.llexternal(
     "cppyy_get_method",
-    [C_SCOPE, rffi.INT], C_METHOD,
+    [C_SCOPE, C_INDEX], C_METHOD,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_get_method(cppscope, method_index):
-    return _c_get_method(cppscope.handle, method_index)
+def c_get_method(cppscope, index):
+    return _c_get_method(cppscope.handle, index)
+_c_get_global_operator = rffi.llexternal(
+    "cppyy_get_global_operator",
+    [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_get_global_operator(nss, lc, rc, op):
+    if nss is not None:
+        return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op)
+    return rffi.cast(WLAVC_INDEX, -1)
 
 # method properties ----------------------------------------------------------
 _c_is_constructor = rffi.llexternal(
     "cppyy_is_constructor",
-    [C_TYPE, rffi.INT], rffi.INT,
+    [C_TYPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_is_constructor(cppclass, method_index):
-    return _c_is_constructor(cppclass.handle, method_index)
+def c_is_constructor(cppclass, index):
+    return _c_is_constructor(cppclass.handle, index)
 _c_is_staticmethod = rffi.llexternal(
     "cppyy_is_staticmethod",
-    [C_TYPE, rffi.INT], rffi.INT,
+    [C_TYPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_is_staticmethod(cppclass, method_index):
-    return _c_is_staticmethod(cppclass.handle, method_index)
+def c_is_staticmethod(cppclass, index):
+    return _c_is_staticmethod(cppclass.handle, index)
 
 # data member reflection information -----------------------------------------
 _c_num_datamembers = rffi.llexternal(
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -1,9 +1,17 @@
-import py, os
+import py, os, sys
+
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.baseobjspace import Wrappable
 
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.lltypesystem import rffi
 from pypy.rlib import libffi, rdynload
 
+from pypy.module.itertools import interp_itertools
+
+
 __all__ = ['identify', 'eci', 'c_load_dictionary']
 
 pkgpath = py.path.local(__file__).dirpath().join(os.pardir)
@@ -61,3 +69,168 @@
         err = rdynload.dlerror()
         raise rdynload.DLOpenError(err)
     return libffi.CDLL(name)       # should return handle to already open file
+
+
+# CINT-specific pythonizations ===============================================
+
+### TTree --------------------------------------------------------------------
+_ttree_Branch = rffi.llexternal(
+    "cppyy_ttree_Branch",
+    [rffi.VOIDP, rffi.CCHARP, rffi.CCHARP, rffi.VOIDP, rffi.INT, rffi.INT], rffi.LONG,
+    threadsafe=False,
+    compilation_info=eci)
+
+ at unwrap_spec(args_w='args_w')
+def ttree_Branch(space, w_self, args_w):
+    """Pythonized version of TTree::Branch(): takes proxy objects and by-passes
+    the CINT-manual layer."""
+
+    from pypy.module.cppyy import interp_cppyy
+    tree_class = interp_cppyy.scope_byname(space, "TTree")
+
+    # sigs to modify (and by-pass CINT):
+    #  1. (const char*, const char*, T**,               Int_t=32000, Int_t=99)
+    #  2. (const char*, T**,                            Int_t=32000, Int_t=99)
+    argc = len(args_w)
+
+    # basic error handling of wrong arguments is best left to the original call,
+    # so that error messages etc. remain consistent in appearance: the following
+    # block may raise TypeError or IndexError to break out anytime
+
+    try:
+        if argc < 2 or 5 < argc:
+            raise TypeError("wrong number of arguments")
+
+        tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=True)
+        if (tree is None) or (tree.cppclass != tree_class):
+            raise TypeError("not a TTree")
+
+        # first argument must always always be cont char*
+        branchname = space.str_w(args_w[0])
+
+        # if args_w[1] is a classname, then case 1, else case 2
+        try:
+            classname = space.str_w(args_w[1])
+            addr_idx  = 2
+            w_address = args_w[addr_idx]
+        except OperationError:
+            addr_idx  = 1
+            w_address = args_w[addr_idx]
+
+        bufsize, splitlevel = 32000, 99
+        if addr_idx+1 < argc: bufsize = space.c_int_w(args_w[addr_idx+1])
+        if addr_idx+2 < argc: splitlevel = space.c_int_w(args_w[addr_idx+2])
+
+        # now retrieve the W_CPPInstance and build other stub arguments
+        space = tree.space    # holds the class cache in State
+        cppinstance = space.interp_w(interp_cppyy.W_CPPInstance, w_address)
+        address = rffi.cast(rffi.VOIDP, cppinstance.get_rawobject())
+        klassname = cppinstance.cppclass.full_name()
+        vtree = rffi.cast(rffi.VOIDP, tree.get_rawobject())
+
+        # call the helper stub to by-pass CINT
+        vbranch = _ttree_Branch(vtree, branchname, klassname, address, bufsize, splitlevel)
+        branch_class = interp_cppyy.scope_byname(space, "TBranch")
+        w_branch = interp_cppyy.wrap_cppobject(
+            space, space.w_None, branch_class, vbranch, isref=False, python_owns=False)
+        return w_branch
+    except (OperationError, TypeError, IndexError), e:
+        pass
+
+    # return control back to the original, unpythonized overload
+    return tree_class.get_overload("Branch").call(w_self, args_w)
+
+def activate_branch(space, w_branch):
+    w_branches = space.call_method(w_branch, "GetListOfBranches")
+    for i in range(space.int_w(space.call_method(w_branches, "GetEntriesFast"))):
+        w_b = space.call_method(w_branches, "At", space.wrap(i))
+        activate_branch(space, w_b)
+    space.call_method(w_branch, "SetStatus", space.wrap(1))
+    space.call_method(w_branch, "ResetReadEntry")
+
+ at unwrap_spec(args_w='args_w')
+def ttree_getattr(space, w_self, args_w):
+    """Specialized __getattr__ for TTree's that allows switching on/off the
+    reading of individual branchs."""
+
+    from pypy.module.cppyy import interp_cppyy
+    tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self)
+
+    # setup branch as a data member and enable it for reading
+    space = tree.space            # holds the class cache in State
+    w_branch = space.call_method(w_self, "GetBranch", args_w[0])
+    w_klassname = space.call_method(w_branch, "GetClassName")
+    klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname))
+    w_obj = klass.construct()
+    #space.call_method(w_branch, "SetStatus", space.wrap(1)) 
+    activate_branch(space, w_branch)
+    space.call_method(w_branch, "SetObject", w_obj)
+    space.call_method(w_branch, "GetEntry", space.wrap(0))
+    space.setattr(w_self, args_w[0], w_obj)
+    return w_obj
+
+class W_TTreeIter(Wrappable):
+    def __init__(self, space, w_tree):
+
+        from pypy.module.cppyy import interp_cppyy
+        tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree)
+        self.tree = tree.get_cppthis(tree.cppclass)
+        self.w_tree = w_tree
+
+        self.getentry = tree.cppclass.get_overload("GetEntry").functions[0]
+        self.current  = 0
+        self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast"))
+
+        space = self.space = tree.space          # holds the class cache in State
+        space.call_method(w_tree, "SetBranchStatus", space.wrap("*"), space.wrap(0))
+
+    def iter_w(self):
+        return self.space.wrap(self)
+
+    def next_w(self):
+        if self.current == self.maxentry:
+            raise OperationError(self.space.w_StopIteration, self.space.w_None)
+        # TODO: check bytes read?
+        self.getentry.call(self.tree, [self.space.wrap(self.current)])
+        self.current += 1 
+        return self.w_tree
+
+W_TTreeIter.typedef = TypeDef(
+    'TTreeIter',
+    __iter__ = interp2app(W_TTreeIter.iter_w),
+    next = interp2app(W_TTreeIter.next_w),
+)
+
+def ttree_iter(space, w_self):
+    """Allow iteration over TTree's. Also initializes branch data members and
+    sets addresses, if needed."""
+    w_treeiter = W_TTreeIter(space, w_self)
+    return w_treeiter
+
+# setup pythonizations for later use at run-time
+_pythonizations = {}
+def register_pythonizations(space):
+    "NOT_RPYTHON"
+
+    ### TTree
+    _pythonizations['ttree_Branch']  = space.wrap(interp2app(ttree_Branch))
+    _pythonizations['ttree_iter']    = space.wrap(interp2app(ttree_iter))
+    _pythonizations['ttree_getattr'] = space.wrap(interp2app(ttree_getattr))
+
+# callback coming in when app-level bound classes have been created
+def pythonize(space, name, w_pycppclass):
+
+    if name == 'TFile':
+        space.setattr(w_pycppclass, space.wrap("__getattr__"),
+                      space.getattr(w_pycppclass, space.wrap("Get")))
+
+    elif name == 'TTree':
+        space.setattr(w_pycppclass, space.wrap("_unpythonized_Branch"),
+                      space.getattr(w_pycppclass, space.wrap("Branch")))
+        space.setattr(w_pycppclass, space.wrap("Branch"), _pythonizations["ttree_Branch"])
+        space.setattr(w_pycppclass, space.wrap("__iter__"), _pythonizations["ttree_iter"])
+        space.setattr(w_pycppclass, space.wrap("__getattr__"), _pythonizations["ttree_getattr"])
+
+    elif name[0:8] == "TVectorT":    # TVectorT<> template
+        space.setattr(w_pycppclass, space.wrap("__len__"),
+                      space.getattr(w_pycppclass, space.wrap("GetNoElements")))
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -41,3 +41,12 @@
 
 def c_load_dictionary(name):
     return libffi.CDLL(name)
+
+
+# Reflex-specific pythonizations
+def register_pythonizations(space):
+    "NOT_RPYTHON"
+    pass
+
+def pythonize(space, name, w_pycppclass):
+    pass
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
@@ -4,12 +4,21 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import jit, libffi, clibffi, rfloat
+from pypy.rlib import libffi, clibffi, rfloat
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
 from pypy.module._rawffi.array import W_Array
 
-from pypy.module.cppyy import helper, capi
+from pypy.module.cppyy import helper, capi, ffitypes
+
+# Converter objects are used to translate between RPython and C++. They are
+# defined by the type name for which they provide conversion. Uses are for
+# function arguments, as well as for read and write access to data members.
+# All type conversions are fully checked.
+#
+# Converter instances are greated by get_converter(<type name>), see below.
+# The name given should be qualified in case there is a specialised, exact
+# match for the qualified type.
 
 
 def get_rawobject(space, w_obj):
@@ -38,6 +47,24 @@
         return rawobject
     return capi.C_NULL_OBJECT
 
+def get_rawbuffer(space, w_obj):
+    try:
+        buf = space.buffer_w(w_obj)
+        return rffi.cast(rffi.VOIDP, buf.get_raw_address())
+    except Exception:
+        pass
+    # special case: allow integer 0 as NULL
+    try:
+        buf = space.int_w(w_obj)
+        if buf == 0:
+            return rffi.cast(rffi.VOIDP, 0)
+    except Exception:
+        pass
+    # special case: allow None as NULL
+    if space.is_true(space.is_(w_obj, space.w_None)):
+        return rffi.cast(rffi.VOIDP, 0)
+    raise TypeError("not an addressable buffer")
+
 
 class TypeConverter(object):
     _immutable_ = True
@@ -59,7 +86,7 @@
         return fieldptr
 
     def _is_abstract(self, space):
-        raise OperationError(space.w_TypeError, space.wrap("no converter available"))
+        raise OperationError(space.w_TypeError, space.wrap("no converter available for '%s'" % self.name))
 
     def convert_argument(self, space, w_obj, address, call_local):
         self._is_abstract(space)
@@ -135,6 +162,20 @@
     def __init__(self, space, array_size):
         self.size = sys.maxint
 
+    def convert_argument(self, space, w_obj, address, call_local):
+        w_tc = space.findattr(w_obj, space.wrap('typecode'))
+        if w_tc is not None and space.str_w(w_tc) != self.typecode:
+            msg = "expected %s pointer type, but received %s" % (self.typecode, space.str_w(w_tc))
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        x = rffi.cast(rffi.LONGP, address)
+        try:
+            x[0] = rffi.cast(rffi.LONG, get_rawbuffer(space, w_obj))
+        except TypeError:
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("raw buffer interface not supported"))
+        ba = rffi.cast(rffi.CCHARP, address)
+        ba[capi.c_function_arg_typeoffset()] = 'o'
+
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         # read access, so no copy needed
         address_value = self._get_raw_address(space, w_obj, offset)
@@ -218,16 +259,8 @@
                              space.wrap('no converter available for type "%s"' % self.name))
 
 
-class BoolConverter(TypeConverter):
+class BoolConverter(ffitypes.typeid(bool), TypeConverter):
     _immutable_ = True
-    libffitype = libffi.types.schar
-
-    def _unwrap_object(self, space, w_obj):
-        arg = space.c_int_w(w_obj)
-        if arg != False and arg != True:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("boolean value should be bool, or integer 1 or 0"))
-        return arg
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.LONGP, address)
@@ -250,26 +283,8 @@
         else:
             address[0] = '\x00'
 
-class CharConverter(TypeConverter):
+class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
     _immutable_ = True
-    libffitype = libffi.types.schar
-
-    def _unwrap_object(self, space, w_value):
-        # allow int to pass to char and make sure that str is of length 1
-        if space.isinstance_w(w_value, space.w_int):
-            ival = space.c_int_w(w_value)
-            if ival < 0 or 256 <= ival:
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("char arg not in range(256)"))
-
-            value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
-        else:
-            value = space.str_w(w_value)
-
-        if len(value) != 1:  
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("char expected, got string of size %d" % len(value)))
-        return value[0] # turn it into a "char" to the annotator
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.CCHARP, address)
@@ -286,156 +301,8 @@
         address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
         address[0] = self._unwrap_object(space, w_value)
 
-
-class ShortConverter(IntTypeConverterMixin, TypeConverter):
+class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
     _immutable_ = True
-    libffitype = libffi.types.sshort
-    c_type     = rffi.SHORT
-    c_ptrtype  = rffi.SHORTP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(rffi.SHORT, capi.c_strtoll(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return rffi.cast(rffi.SHORT, space.int_w(w_obj))
-
-class ConstShortRefConverter(ConstRefNumericTypeConverterMixin, ShortConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-class UnsignedShortConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.sshort
-    c_type     = rffi.USHORT
-    c_ptrtype  = rffi.USHORTP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return rffi.cast(self.c_type, space.int_w(w_obj))
-
-class ConstUnsignedShortRefConverter(ConstRefNumericTypeConverterMixin, UnsignedShortConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-class IntConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.sint
-    c_type     = rffi.INT
-    c_ptrtype  = rffi.INTP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return rffi.cast(self.c_type, space.c_int_w(w_obj))
-
-class ConstIntRefConverter(ConstRefNumericTypeConverterMixin, IntConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-class UnsignedIntConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.uint
-    c_type     = rffi.UINT
-    c_ptrtype  = rffi.UINTP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return rffi.cast(self.c_type, space.uint_w(w_obj))
-
-class ConstUnsignedIntRefConverter(ConstRefNumericTypeConverterMixin, UnsignedIntConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-class LongConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.slong
-    c_type     = rffi.LONG
-    c_ptrtype  = rffi.LONGP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return space.int_w(w_obj)
-
-class ConstLongRefConverter(ConstRefNumericTypeConverterMixin, LongConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-    typecode = 'r'
-
-    def convert_argument(self, space, w_obj, address, call_local):
-        x = rffi.cast(self.c_ptrtype, address)
-        x[0] = self._unwrap_object(space, w_obj)
-        ba = rffi.cast(rffi.CCHARP, address)
-        ba[capi.c_function_arg_typeoffset()] = self.typecode
-
-class LongLongConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.slong
-    c_type     = rffi.LONGLONG
-    c_ptrtype  = rffi.LONGLONGP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return space.r_longlong_w(w_obj)
-
-class ConstLongLongRefConverter(ConstRefNumericTypeConverterMixin, LongLongConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-    typecode = 'r'
-
-    def convert_argument(self, space, w_obj, address, call_local):
-        x = rffi.cast(self.c_ptrtype, address)
-        x[0] = self._unwrap_object(space, w_obj)
-        ba = rffi.cast(rffi.CCHARP, address)
-        ba[capi.c_function_arg_typeoffset()] = self.typecode
-
-class UnsignedLongConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.ulong
-    c_type     = rffi.ULONG
-    c_ptrtype  = rffi.ULONGP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return space.uint_w(w_obj)
-
-class ConstUnsignedLongRefConverter(ConstRefNumericTypeConverterMixin, UnsignedLongConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-class UnsignedLongLongConverter(IntTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.ulong
-    c_type     = rffi.ULONGLONG
-    c_ptrtype  = rffi.ULONGLONGP
-
-    def __init__(self, space, default):
-        self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
-    def _unwrap_object(self, space, w_obj):
-        return space.r_ulonglong_w(w_obj)
-
-class ConstUnsignedLongLongRefConverter(ConstRefNumericTypeConverterMixin, UnsignedLongLongConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-
-class FloatConverter(FloatTypeConverterMixin, TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.float
-    c_type     = rffi.FLOAT
-    c_ptrtype  = rffi.FLOATP
-    typecode   = 'f'
 
     def __init__(self, space, default):
         if default:
@@ -444,9 +311,6 @@
             fval = float(0.)
         self.default = r_singlefloat(fval)
 
-    def _unwrap_object(self, space, w_obj):
-        return r_singlefloat(space.float_w(w_obj))
-
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = self._get_raw_address(space, w_obj, offset)
         rffiptr = rffi.cast(self.c_ptrtype, address)
@@ -461,12 +325,8 @@
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
-class DoubleConverter(FloatTypeConverterMixin, TypeConverter):
+class DoubleConverter(ffitypes.typeid(rffi.DOUBLE), FloatTypeConverterMixin, TypeConverter):
     _immutable_ = True
-    libffitype = libffi.types.double
-    c_type     = rffi.DOUBLE
-    c_ptrtype  = rffi.DOUBLEP
-    typecode   = 'd'
 
     def __init__(self, space, default):
         if default:
@@ -474,9 +334,6 @@
         else:
             self.default = rffi.cast(self.c_type, 0.)
 
-    def _unwrap_object(self, space, w_obj):
-        return space.float_w(w_obj)
-
 class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
     _immutable_ = True
     libffitype = libffi.types.pointer
@@ -507,9 +364,12 @@
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.VOIDPP, address)
-        x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         ba = rffi.cast(rffi.CCHARP, address)
-        ba[capi.c_function_arg_typeoffset()] = 'a'
+        try:
+            x[0] = get_rawbuffer(space, w_obj)
+        except TypeError:
+            x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
+        ba[capi.c_function_arg_typeoffset()] = 'o'
 
     def convert_argument_libffi(self, space, w_obj, argchain, call_local):
         argchain.arg(get_rawobject(space, w_obj))
@@ -519,27 +379,26 @@
     uses_local = True
 
     def convert_argument(self, space, w_obj, address, call_local):
+        x = rffi.cast(rffi.VOIDPP, address)
+        ba = rffi.cast(rffi.CCHARP, address)
         r = rffi.cast(rffi.VOIDPP, call_local)
-        r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
-        x = rffi.cast(rffi.VOIDPP, address)
+        try:
+            r[0] = get_rawbuffer(space, w_obj)
+        except TypeError:
+            r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         x[0] = rffi.cast(rffi.VOIDP, call_local)
-        address = rffi.cast(capi.C_OBJECT, address)
-        ba = rffi.cast(rffi.CCHARP, address)
         ba[capi.c_function_arg_typeoffset()] = 'a'
 
     def finalize_call(self, space, w_obj, call_local):
         r = rffi.cast(rffi.VOIDPP, call_local)
-        set_rawobject(space, w_obj, r[0])
+        try:
+            set_rawobject(space, w_obj, r[0])
+        except OperationError:
+            pass             # no set on buffer/array/None
 
-class VoidPtrRefConverter(TypeConverter):
+class VoidPtrRefConverter(VoidPtrPtrConverter):
     _immutable_ = True
-
-    def convert_argument(self, space, w_obj, address, call_local):
-        x = rffi.cast(rffi.VOIDPP, address)
-        x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
-        ba = rffi.cast(rffi.CCHARP, address)
-        ba[capi.c_function_arg_typeoffset()] = 'r'
-
+    uses_local = True
 
 class InstancePtrConverter(TypeConverter):
     _immutable_ = True
@@ -631,13 +490,13 @@
 
     def _unwrap_object(self, space, w_obj):
         try:
-           charp = rffi.str2charp(space.str_w(w_obj))
-           arg = capi.c_charp2stdstring(charp)
-           rffi.free_charp(charp)
-           return arg
+            charp = rffi.str2charp(space.str_w(w_obj))
+            arg = capi.c_charp2stdstring(charp)
+            rffi.free_charp(charp)
+            return arg
         except OperationError:
-           arg = InstanceConverter._unwrap_object(self, space, w_obj)
-           return capi.c_stdstring2stdstring(arg)
+            arg = InstanceConverter._unwrap_object(self, space, w_obj)
+            return capi.c_stdstring2stdstring(arg)
 
     def to_memory(self, space, w_obj, w_value, offset):
         try:
@@ -672,7 +531,7 @@
         from pypy.module.cpyext.pyobject import make_ref
         ref = make_ref(space, w_obj)
         x = rffi.cast(rffi.VOIDPP, address)
-        x[0] = rffi.cast(rffi.VOIDP, ref);
+        x[0] = rffi.cast(rffi.VOIDP, ref)
         ba = rffi.cast(rffi.CCHARP, address)
         ba[capi.c_function_arg_typeoffset()] = 'a'
 
@@ -719,7 +578,7 @@
 
     #   2) match of decorated, unqualified type
     compound = helper.compound(name)
-    clean_name = helper.clean_type(name)
+    clean_name = capi.c_resolve_name(helper.clean_type(name))
     try:
         # array_index may be negative to indicate no size or no size found
         array_size = helper.array_size(name)
@@ -743,8 +602,8 @@
         elif compound == "":
             return InstanceConverter(space, cppclass)
     elif capi.c_is_enum(clean_name):
-        return UnsignedIntConverter(space, default)
-    
+        return _converters['unsigned'](space, default)
+
     #   5) void converter, which fails on use
     #
     # return a void converter here, so that the class can be build even
@@ -754,59 +613,96 @@
 
 _converters["bool"]                     = BoolConverter
 _converters["char"]                     = CharConverter
-_converters["unsigned char"]            = CharConverter
-_converters["short int"]                = ShortConverter
-_converters["const short int&"]         = ConstShortRefConverter
-_converters["short"]                    = _converters["short int"]
-_converters["const short&"]             = _converters["const short int&"]
-_converters["unsigned short int"]       = UnsignedShortConverter
-_converters["const unsigned short int&"] = ConstUnsignedShortRefConverter
-_converters["unsigned short"]           = _converters["unsigned short int"]
-_converters["const unsigned short&"]    = _converters["const unsigned short int&"]
-_converters["int"]                      = IntConverter
-_converters["const int&"]               = ConstIntRefConverter
-_converters["unsigned int"]             = UnsignedIntConverter
-_converters["const unsigned int&"]      = ConstUnsignedIntRefConverter
-_converters["long int"]                 = LongConverter
-_converters["const long int&"]          = ConstLongRefConverter
-_converters["long"]                     = _converters["long int"]
-_converters["const long&"]              = _converters["const long int&"]
-_converters["unsigned long int"]        = UnsignedLongConverter
-_converters["const unsigned long int&"] = ConstUnsignedLongRefConverter
-_converters["unsigned long"]            = _converters["unsigned long int"]
-_converters["const unsigned long&"]     = _converters["const unsigned long int&"]
-_converters["long long int"]            = LongLongConverter
-_converters["const long long int&"]     = ConstLongLongRefConverter
-_converters["long long"]                = _converters["long long int"]
-_converters["const long long&"]         = _converters["const long long int&"]
-_converters["unsigned long long int"]   = UnsignedLongLongConverter
-_converters["const unsigned long long int&"] = ConstUnsignedLongLongRefConverter
-_converters["unsigned long long"]       = _converters["unsigned long long int"]
-_converters["const unsigned long long&"] = _converters["const unsigned long long int&"]
 _converters["float"]                    = FloatConverter
 _converters["const float&"]             = ConstFloatRefConverter
 _converters["double"]                   = DoubleConverter
 _converters["const double&"]            = ConstDoubleRefConverter
 _converters["const char*"]              = CStringConverter
-_converters["char*"]                    = CStringConverter
 _converters["void*"]                    = VoidPtrConverter
 _converters["void**"]                   = VoidPtrPtrConverter
 _converters["void*&"]                   = VoidPtrRefConverter
 
 # special cases (note: CINT backend requires the simple name 'string')
 _converters["std::basic_string<char>"]           = StdStringConverter
-_converters["string"]                            = _converters["std::basic_string<char>"]
 _converters["const std::basic_string<char>&"]    = StdStringConverter     # TODO: shouldn't copy
-_converters["const string&"]                     = _converters["const std::basic_string<char>&"]
 _converters["std::basic_string<char>&"]          = StdStringRefConverter
-_converters["string&"]                           = _converters["std::basic_string<char>&"]
 
 _converters["PyObject*"]                         = PyObjectConverter
-_converters["_object*"]                          = _converters["PyObject*"]
 
+# add basic (builtin) converters
+def _build_basic_converters():
+    "NOT_RPYTHON"
+    # signed types (use strtoll in setting of default in __init__)
+    type_info = (
+        (rffi.SHORT,      ("short", "short int")),
+        (rffi.INT,        ("int",)),
+    )
+
+    # constref converters exist only b/c the stubs take constref by value, whereas
+    # libffi takes them by pointer (hence it needs the fast-path in testing); note
+    # that this is list is not complete, as some classes are specialized
+
+    for c_type, names in type_info:
+        class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+            _immutable_ = True
+            def __init__(self, space, default):
+                self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
+        class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
+            _immutable_ = True
+            libffitype = libffi.types.pointer
+        for name in names:
+            _converters[name] = BasicConverter
+            _converters["const "+name+"&"] = ConstRefConverter
+
+    type_info = (
+        (rffi.LONG,       ("long", "long int")),
+        (rffi.LONGLONG,   ("long long", "long long int")),
+    )
+
+    for c_type, names in type_info:
+        class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+            _immutable_ = True
+            def __init__(self, space, default):
+                self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
+        class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
+            _immutable_ = True
+            libffitype = libffi.types.pointer
+            typecode = 'r'
+            def convert_argument(self, space, w_obj, address, call_local):
+                x = rffi.cast(self.c_ptrtype, address)
+                x[0] = self._unwrap_object(space, w_obj)
+                ba = rffi.cast(rffi.CCHARP, address)
+                ba[capi.c_function_arg_typeoffset()] = self.typecode
+        for name in names:
+            _converters[name] = BasicConverter
+            _converters["const "+name+"&"] = ConstRefConverter
+
+    # unsigned integer types (use strtoull in setting of default in __init__)
+    type_info = (
+        (rffi.USHORT,     ("unsigned short", "unsigned short int")),
+        (rffi.UINT,       ("unsigned", "unsigned int")),
+        (rffi.ULONG,      ("unsigned long", "unsigned long int")),
+        (rffi.ULONGLONG,  ("unsigned long long", "unsigned long long int")),
+    )
+
+    for c_type, names in type_info:
+        class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+            _immutable_ = True
+            def __init__(self, space, default):
+                self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
+        class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
+            _immutable_ = True
+            libffitype = libffi.types.pointer
+        for name in names:
+            _converters[name] = BasicConverter
+            _converters["const "+name+"&"] = ConstRefConverter
+_build_basic_converters()
+
+# create the array and pointer converters; all real work is in the mixins
 def _build_array_converters():
     "NOT_RPYTHON"
     array_info = (
+        ('b', rffi.sizeof(rffi.UCHAR),  ("bool",)),    # is debatable, but works ...
         ('h', rffi.sizeof(rffi.SHORT),  ("short int", "short")),
         ('H', rffi.sizeof(rffi.USHORT), ("unsigned short int", "unsigned short")),
         ('i', rffi.sizeof(rffi.INT),    ("int",)),
@@ -817,16 +713,35 @@
         ('d', rffi.sizeof(rffi.DOUBLE), ("double",)),
     )
 
-    for info in array_info:
+    for tcode, tsize, names in array_info:
         class ArrayConverter(ArrayTypeConverterMixin, TypeConverter):
             _immutable_ = True
-            typecode = info[0]
-            typesize = info[1]
+            typecode = tcode
+            typesize = tsize
         class PtrConverter(PtrTypeConverterMixin, TypeConverter):
             _immutable_ = True
-            typecode = info[0]
-            typesize = info[1]
-        for name in info[2]:
+            typecode = tcode
+            typesize = tsize
+        for name in names:
             _a_converters[name+'[]'] = ArrayConverter
             _a_converters[name+'*']  = PtrConverter
 _build_array_converters()
+
+# add another set of aliased names
+def _add_aliased_converters():
+    "NOT_RPYTHON"
+    aliases = (
+        ("char",                            "unsigned char"),
+        ("const char*",                     "char*"),
+
+        ("std::basic_string<char>",         "string"),
+        ("const std::basic_string<char>&",  "const string&"),
+        ("std::basic_string<char>&",        "string&"),
+
+        ("PyObject*",                       "_object*"),
+    )
+ 
+    for c_type, alias in aliases:
+        _converters[alias] = _converters[c_type]
+_add_aliased_converters()
+
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
@@ -6,9 +6,22 @@
 from pypy.rlib import libffi, clibffi
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
-from pypy.module._rawffi.array import W_Array
+from pypy.module._rawffi.array import W_Array, W_ArrayInstance
 
-from pypy.module.cppyy import helper, capi
+from pypy.module.cppyy import helper, capi, ffitypes
+
+# Executor objects are used to dispatch C++ methods. They are defined by their
+# return type only: arguments are converted by Converter objects, and Executors
+# only deal with arrays of memory that are either passed to a stub or libffi.
+# No argument checking or conversions are done.
+#
+# If a libffi function is not implemented, FastCallNotPossible is raised. If a
+# stub function is missing (e.g. if no reflection info is available for the
+# return type), an app-level TypeError is raised.
+#
+# Executor instances are created by get_executor(<return type name>), see
+# below. The name given should be qualified in case there is a specialised,
+# exact match for the qualified type.
 
 
 NULL = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
@@ -39,6 +52,14 @@
         lresult = capi.c_call_l(cppmethod, cppthis, num_args, args)
         address = rffi.cast(rffi.ULONG, lresult)
         arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap(self.typecode)))
+        if address == 0:
+            # TODO: fix this hack; fromaddress() will allocate memory if address
+            # is null and there seems to be no way around it (ll_buffer can not
+            # be touched directly)
+            nullarr = arr.fromaddress(space, address, 0)
+            assert isinstance(nullarr, W_ArrayInstance)
+            nullarr.free(space)
+            return nullarr
         return arr.fromaddress(space, address, sys.maxint)
 
 
@@ -55,175 +76,50 @@
         return space.w_None
 
 
-class BoolExecutor(FunctionExecutor):
+class NumericExecutorMixin(object):
+    _mixin_ = True
     _immutable_ = True
-    libffitype = libffi.types.schar
+
+    def _wrap_object(self, space, obj):
+        return space.wrap(obj)
 
     def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_b(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
+        result = self.c_stubcall(cppmethod, cppthis, num_args, args)
+        return self._wrap_object(space, rffi.cast(self.c_type, result))
 
     def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.CHAR)
-        return space.wrap(bool(ord(result)))
+        result = libffifunc.call(argchain, self.c_type)
+        return self._wrap_object(space, result)
 
-class CharExecutor(FunctionExecutor):
+class NumericRefExecutorMixin(object):
+    _mixin_ = True
     _immutable_ = True
-    libffitype = libffi.types.schar
 
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_c(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
+    def __init__(self, space, extra):
+        FunctionExecutor.__init__(self, space, extra)
+        self.do_assign = False
+        self.item = rffi.cast(self.c_type, 0)
 
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.CHAR)
-        return space.wrap(result)
+    def set_item(self, space, w_item):
+        self.item = self._unwrap_object(space, w_item)
+        self.do_assign = True
 
-class ShortExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sshort
+    def _wrap_object(self, space, obj):
+        return space.wrap(rffi.cast(self.c_type, obj))
 
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_h(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.SHORT)
-        return space.wrap(result)
-
-class IntExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sint
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_i(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.INT)
-        return space.wrap(result)
-
-class UnsignedIntExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.uint
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.UINT, result))
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_l(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.UINT)
-        return space.wrap(result)
-
-class LongExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.slong
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_l(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.LONG)
-        return space.wrap(result)
-
-class UnsignedLongExecutor(LongExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.ulong
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.ULONG, result))
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.ULONG)
-        return space.wrap(result)
-
-class LongLongExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sint64
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_ll(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.LONGLONG)
-        return space.wrap(result)
-
-class UnsignedLongLongExecutor(LongLongExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.uint64
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.ULONGLONG, result))
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.ULONGLONG)
-        return space.wrap(result)
-
-class ConstIntRefExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-    def _wrap_result(self, space, result):
-        intptr = rffi.cast(rffi.INTP, result)
-        return space.wrap(intptr[0])
+    def _wrap_reference(self, space, rffiptr):
+        if self.do_assign:
+            rffiptr[0] = self.item
+        self.do_assign = False
+        return self._wrap_object(space, rffiptr[0])    # all paths, for rtyper
 
     def execute(self, space, cppmethod, cppthis, num_args, args):
         result = capi.c_call_r(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
+        return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
 
     def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.INTP)
-        return space.wrap(result[0])
-
-class ConstLongRefExecutor(ConstIntRefExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
-
-    def _wrap_result(self, space, result):
-        longptr = rffi.cast(rffi.LONGP, result)
-        return space.wrap(longptr[0])
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.LONGP)
-        return space.wrap(result[0])
-
-class FloatExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.float
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_f(cppmethod, cppthis, num_args, args)
-        return space.wrap(float(result))
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.FLOAT)
-        return space.wrap(float(result))
-
-class DoubleExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.double
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_d(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.DOUBLE)
-        return space.wrap(result)
+        result = libffifunc.call(argchain, self.c_ptrtype)
+        return self._wrap_reference(space, result)
 
 
 class CStringExecutor(FunctionExecutor):
@@ -236,35 +132,6 @@
         return space.wrap(result)
 
 
-class ShortPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'h'
-
-class IntPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'i'
-
-class UnsignedIntPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'I'
-
-class LongPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'l'
-
-class UnsignedLongPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'L'
-
-class FloatPtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'f'
-
-class DoublePtrExecutor(PtrTypeExecutor):
-    _immutable_ = True
-    typecode = 'd'
-
-
 class ConstructorExecutor(VoidExecutor):
     _immutable_ = True
 
@@ -380,7 +247,7 @@
         pass
 
     compound = helper.compound(name)
-    clean_name = helper.clean_type(name)
+    clean_name = capi.c_resolve_name(helper.clean_type(name))
 
     #   1a) clean lookup
     try:
@@ -410,7 +277,7 @@
         elif compound == "**" or compound == "*&":
             return InstancePtrPtrExecutor(space, cppclass)
     elif capi.c_is_enum(clean_name):
-        return UnsignedIntExecutor(space, None)
+        return _executors['unsigned int'](space, None)
 
     # 4) additional special cases
     # ... none for now
@@ -421,46 +288,80 @@
 
 _executors["void"]                = VoidExecutor
 _executors["void*"]               = PtrTypeExecutor
-_executors["bool"]                = BoolExecutor
-_executors["char"]                = CharExecutor
-_executors["char*"]               = CStringExecutor
-_executors["unsigned char"]       = CharExecutor
-_executors["short int"]           = ShortExecutor
-_executors["short"]               = _executors["short int"]
-_executors["short int*"]          = ShortPtrExecutor
-_executors["short*"]              = _executors["short int*"]
-_executors["unsigned short int"]  = ShortExecutor
-_executors["unsigned short"]      = _executors["unsigned short int"]
-_executors["unsigned short int*"] = ShortPtrExecutor
-_executors["unsigned short*"]     = _executors["unsigned short int*"]
-_executors["int"]                 = IntExecutor
-_executors["int*"]                = IntPtrExecutor
-_executors["const int&"]          = ConstIntRefExecutor
-_executors["int&"]                = ConstIntRefExecutor
-_executors["unsigned int"]        = UnsignedIntExecutor
-_executors["unsigned int*"]       = UnsignedIntPtrExecutor
-_executors["long int"]            = LongExecutor
-_executors["long"]                = _executors["long int"]
-_executors["long int*"]           = LongPtrExecutor
-_executors["long*"]               = _executors["long int*"]
-_executors["unsigned long int"]   = UnsignedLongExecutor
-_executors["unsigned long"]       = _executors["unsigned long int"]
-_executors["unsigned long int*"]  = UnsignedLongPtrExecutor
-_executors["unsigned long*"]      = _executors["unsigned long int*"]
-_executors["long long int"]       = LongLongExecutor
-_executors["long long"]           = _executors["long long int"]
-_executors["unsigned long long int"] = UnsignedLongLongExecutor
-_executors["unsigned long long"]  = _executors["unsigned long long int"]
-_executors["float"]               = FloatExecutor
-_executors["float*"]              = FloatPtrExecutor
-_executors["double"]              = DoubleExecutor
-_executors["double*"]             = DoublePtrExecutor
+_executors["const char*"]         = CStringExecutor
 
+# special cases
 _executors["constructor"]         = ConstructorExecutor
 
-# special cases (note: CINT backend requires the simple name 'string')
-_executors["std::basic_string<char>"]        = StdStringExecutor
-_executors["string"]                         = _executors["std::basic_string<char>"]
+_executors["std::basic_string<char>"]         = StdStringExecutor
+_executors["const std::basic_string<char>&"]  = StdStringExecutor
+_executors["std::basic_string<char>&"]        = StdStringExecutor    # TODO: shouldn't copy
 
 _executors["PyObject*"]           = PyObjectExecutor
-_executors["_object*"]            = _executors["PyObject*"]
+
+# add basic (builtin) executors
+def _build_basic_executors():
+    "NOT_RPYTHON"
+    type_info = (
+        (bool,            capi.c_call_b,   ("bool",)),
+        (rffi.CHAR,       capi.c_call_c,   ("char", "unsigned char")),
+        (rffi.SHORT,      capi.c_call_h,   ("short", "short int", "unsigned short", "unsigned short int")),
+        (rffi.INT,        capi.c_call_i,   ("int",)),
+        (rffi.UINT,       capi.c_call_l,   ("unsigned", "unsigned int")),
+        (rffi.LONG,       capi.c_call_l,   ("long", "long int")),
+        (rffi.ULONG,      capi.c_call_l,   ("unsigned long", "unsigned long int")),
+        (rffi.LONGLONG,   capi.c_call_ll,  ("long long", "long long int")),
+        (rffi.ULONGLONG,  capi.c_call_ll,  ("unsigned long long", "unsigned long long int")),
+        (rffi.FLOAT,      capi.c_call_f,   ("float",)),
+        (rffi.DOUBLE,     capi.c_call_d,   ("double",)),
+    )
+
+    for c_type, stub, names in type_info:
+        class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, FunctionExecutor):
+            _immutable_ = True
+            c_stubcall  = staticmethod(stub)
+        class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, FunctionExecutor):
+            _immutable_ = True
+            libffitype = libffi.types.pointer
+        for name in names:
+            _executors[name]              = BasicExecutor
+            _executors[name+'&']          = BasicRefExecutor
+            _executors['const '+name+'&'] = BasicRefExecutor     # no copy needed for builtins
+_build_basic_executors()
+
+# create the pointer executors; all real work is in the PtrTypeExecutor, since
+# all pointer types are of the same size
+def _build_ptr_executors():
+    "NOT_RPYTHON"
+    ptr_info = (
+        ('b', ("bool",)),     # really unsigned char, but this works ...
+        ('h', ("short int", "short")),
+        ('H', ("unsigned short int", "unsigned short")),
+        ('i', ("int",)),
+        ('I', ("unsigned int", "unsigned")),
+        ('l', ("long int", "long")),
+        ('L', ("unsigned long int", "unsigned long")),
+        ('f', ("float",)),
+        ('d', ("double",)),
+    )
+
+    for tcode, names in ptr_info:
+        class PtrExecutor(PtrTypeExecutor):
+            _immutable_ = True
+            typecode = tcode
+        for name in names:
+            _executors[name+'*'] = PtrExecutor
+_build_ptr_executors()
+
+# add another set of aliased names
+def _add_aliased_executors():
+    "NOT_RPYTHON"
+    aliases = (
+        ("const char*",                     "char*"),
+        ("std::basic_string<char>",         "string"),
+        ("PyObject*",                       "_object*"),
+    )
+
+    for c_type, alias in aliases:
+        _executors[alias] = _executors[c_type]
+_add_aliased_executors()
diff --git a/pypy/module/cppyy/ffitypes.py b/pypy/module/cppyy/ffitypes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/ffitypes.py
@@ -0,0 +1,176 @@
+from pypy.interpreter.error import OperationError
+
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib.rarithmetic import r_singlefloat
+from pypy.rlib import libffi, rfloat
+
+# Mixins to share between converter and executor classes (in converter.py and
+# executor.py, respectively). Basically these mixins allow grouping of the
+# sets of libffi, rffi, and different space unwrapping calls. To get the right
+# mixin, a non-RPython function typeid() is used.
+
+
+class BoolTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.uchar
+    c_type      = rffi.UCHAR
+    c_ptrtype   = rffi.UCHARP
+
+    def _unwrap_object(self, space, w_obj):
+        arg = space.c_int_w(w_obj)
+        if arg != False and arg != True:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("boolean value should be bool, or integer 1 or 0"))
+        return arg
+
+    def _wrap_object(self, space, obj):
+        return space.wrap(bool(ord(rffi.cast(rffi.CHAR, obj))))
+
+class CharTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.schar
+    c_type      = rffi.CHAR
+    c_ptrtype   = rffi.CCHARP           # there's no such thing as rffi.CHARP
+
+    def _unwrap_object(self, space, w_value):
+        # allow int to pass to char and make sure that str is of length 1
+        if space.isinstance_w(w_value, space.w_int):
+            ival = space.c_int_w(w_value)
+            if ival < 0 or 256 <= ival:
+                raise OperationError(space.w_ValueError,
+                                     space.wrap("char arg not in range(256)"))
+
+            value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
+        else:
+            value = space.str_w(w_value)
+
+        if len(value) != 1:  
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("char expected, got string of size %d" % len(value)))
+        return value[0] # turn it into a "char" to the annotator
+
+class ShortTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.sshort
+    c_type      = rffi.SHORT
+    c_ptrtype   = rffi.SHORTP
+
+    def _unwrap_object(self, space, w_obj):
+        return rffi.cast(rffi.SHORT, space.int_w(w_obj))
+
+class UShortTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.ushort
+    c_type      = rffi.USHORT
+    c_ptrtype   = rffi.USHORTP
+
+    def _unwrap_object(self, space, w_obj):
+        return rffi.cast(self.c_type, space.int_w(w_obj))
+
+class IntTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.sint
+    c_type      = rffi.INT
+    c_ptrtype   = rffi.INTP
+
+    def _unwrap_object(self, space, w_obj):
+        return rffi.cast(self.c_type, space.c_int_w(w_obj))
+
+class UIntTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.uint
+    c_type      = rffi.UINT
+    c_ptrtype   = rffi.UINTP
+
+    def _unwrap_object(self, space, w_obj):
+        return rffi.cast(self.c_type, space.uint_w(w_obj))
+
+class LongTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype = libffi.types.slong
+    c_type     =  rffi.LONG
+    c_ptrtype   = rffi.LONGP
+
+    def _unwrap_object(self, space, w_obj):
+        return space.int_w(w_obj)
+
+class ULongTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype = libffi.types.ulong
+    c_type     = rffi.ULONG
+    c_ptrtype  = rffi.ULONGP
+
+    def _unwrap_object(self, space, w_obj):
+        return space.uint_w(w_obj)
+
+class LongLongTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.sint64
+    c_type      = rffi.LONGLONG
+    c_ptrtype   = rffi.LONGLONGP
+
+    def _unwrap_object(self, space, w_obj):
+        return space.r_longlong_w(w_obj)
+
+class ULongLongTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype = libffi.types.uint64
+    c_type     = rffi.ULONGLONG
+    c_ptrtype  = rffi.ULONGLONGP
+
+    def _unwrap_object(self, space, w_obj):
+        return space.r_ulonglong_w(w_obj)
+
+class FloatTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.float
+    c_type      = rffi.FLOAT
+    c_ptrtype   = rffi.FLOATP
+    typecode    = 'f'
+
+    def _unwrap_object(self, space, w_obj):
+        return r_singlefloat(space.float_w(w_obj))
+
+    def _wrap_object(self, space, obj):
+        return space.wrap(float(obj))
+
+class DoubleTypeMixin(object):
+    _mixin_     = True
+    _immutable_ = True
+    libffitype  = libffi.types.double
+    c_type      = rffi.DOUBLE
+    c_ptrtype   = rffi.DOUBLEP
+    typecode    = 'd'
+
+    def _unwrap_object(self, space, w_obj):
+        return space.float_w(w_obj)
+
+
+def typeid(c_type):
+    "NOT_RPYTHON"
+    if c_type == bool:            return BoolTypeMixin
+    if c_type == rffi.CHAR:       return CharTypeMixin
+    if c_type == rffi.SHORT:      return ShortTypeMixin
+    if c_type == rffi.USHORT:     return UShortTypeMixin
+    if c_type == rffi.INT:        return IntTypeMixin
+    if c_type == rffi.UINT:       return UIntTypeMixin
+    if c_type == rffi.LONG:       return LongTypeMixin
+    if c_type == rffi.ULONG:      return ULongTypeMixin
+    if c_type == rffi.LONGLONG:   return LongLongTypeMixin
+    if c_type == rffi.ULONGLONG:  return ULongLongTypeMixin
+    if c_type == rffi.FLOAT:      return FloatTypeMixin
+    if c_type == rffi.DOUBLE:     return DoubleTypeMixin
+
+    # should never get here
+    raise TypeError("unknown rffi type: %s" % c_type)
diff --git a/pypy/module/cppyy/helper.py b/pypy/module/cppyy/helper.py
--- a/pypy/module/cppyy/helper.py
+++ b/pypy/module/cppyy/helper.py
@@ -43,7 +43,7 @@
     if name.endswith("]"):                       # array type?
         idx = name.rfind("[")
         if 0 < idx:
-             name = name[:idx]
+            name = name[:idx]
     elif name.endswith(">"):                     # template type?
         idx = name.find("<")
         if 0 < idx:      # always true, but just so that the translater knows
@@ -90,10 +90,10 @@
             return nargs and "__sub__" or "__neg__"
 
         if op == "++":  # prefix v.s. postfix increment (not python)
-            return nargs and "__postinc__" or "__preinc__";
+            return nargs and "__postinc__" or "__preinc__"
 
         if op == "--":  # prefix v.s. postfix decrement (not python)
-            return nargs and "__postdec__" or "__predec__";
+            return nargs and "__postdec__" or "__predec__"
 
         # operator could have been a conversion using a typedef (this lookup
         # is put at the end only as it is unlikely and may trigger unwanted
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
@@ -11,9 +11,13 @@
     typedef cppyy_scope_t cppyy_type_t;
     typedef long cppyy_object_t;
     typedef long cppyy_method_t;
+    typedef long cppyy_index_t;
     typedef void* (*cppyy_methptrgetter_t)(cppyy_object_t);
 
     /* name to opaque C++ scope representation -------------------------------- */
+    int cppyy_num_scopes(cppyy_scope_t parent);
+    char* cppyy_scope_name(cppyy_scope_t parent, int iscope);
+
     char* cppyy_resolve_name(const char* cppitem_name);
     cppyy_scope_t cppyy_get_scope(const char* scope_name);
     cppyy_type_t cppyy_get_template(const char* template_name);
@@ -26,13 +30,13 @@
 
     /* method/function dispatching -------------------------------------------- */
     void   cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
-    int    cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
+    unsigned char cppyy_call_b(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);
     short  cppyy_call_h(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);
     long   cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
     long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
-    double 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);
     double cppyy_call_d(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);
@@ -41,7 +45,7 @@
     void cppyy_constructor(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
     cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, cppyy_type_t result_type);
 
-    cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_scope_t scope, int method_index);
+    cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_scope_t scope, cppyy_index_t idx);
 
     /* handling of function argument buffer ----------------------------------- */
     void*  cppyy_allocate_function_args(size_t nargs);
@@ -66,21 +70,24 @@
 
     /* method/function reflection information --------------------------------- */
     int cppyy_num_methods(cppyy_scope_t scope);
-    char* cppyy_method_name(cppyy_scope_t scope, int method_index);
-    char* cppyy_method_result_type(cppyy_scope_t scope, int method_index);
-    int cppyy_method_num_args(cppyy_scope_t scope, int method_index);
-    int cppyy_method_req_args(cppyy_scope_t scope, int method_index);
-    char* cppyy_method_arg_type(cppyy_scope_t scope, int method_index, int arg_index);
-    char* cppyy_method_arg_default(cppyy_scope_t scope, int method_index, int arg_index);
-    char* cppyy_method_signature(cppyy_scope_t scope, int method_index);
+    cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth);
+    cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t scope, const char* name);
 
-    int cppyy_method_index(cppyy_scope_t scope, const char* name);
+    char* cppyy_method_name(cppyy_scope_t scope, cppyy_index_t idx);
+    char* cppyy_method_result_type(cppyy_scope_t scope, cppyy_index_t idx);
+    int cppyy_method_num_args(cppyy_scope_t scope, cppyy_index_t idx);
+    int cppyy_method_req_args(cppyy_scope_t scope, cppyy_index_t idx);
+    char* cppyy_method_arg_type(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
+    char* cppyy_method_arg_default(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
+    char* cppyy_method_signature(cppyy_scope_t scope, cppyy_index_t idx);
 
-    cppyy_method_t cppyy_get_method(cppyy_scope_t scope, int method_index);
+    cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx);
+    cppyy_index_t cppyy_get_global_operator(
+        cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op);
 
     /* method properties -----------------------------------------------------  */
-    int cppyy_is_constructor(cppyy_type_t type, int method_index);
-    int cppyy_is_staticmethod(cppyy_type_t type, int method_index);
+    int cppyy_is_constructor(cppyy_type_t type, cppyy_index_t idx);
+    int cppyy_is_staticmethod(cppyy_type_t type, cppyy_index_t idx);
 
     /* data member reflection information ------------------------------------  */
     int cppyy_num_datamembers(cppyy_scope_t scope);
@@ -95,9 +102,9 @@
     int cppyy_is_staticdata(cppyy_type_t type, int datamember_index);
 
     /* misc helpers ----------------------------------------------------------- */
-    void cppyy_free(void* ptr);
     long long cppyy_strtoll(const char* str);
     unsigned long long cppyy_strtuoll(const char* str);
+    void cppyy_free(void* ptr);
 
     cppyy_object_t cppyy_charp2stdstring(const char* str);
     cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
diff --git a/pypy/module/cppyy/include/cintcwrapper.h b/pypy/module/cppyy/include/cintcwrapper.h
--- a/pypy/module/cppyy/include/cintcwrapper.h
+++ b/pypy/module/cppyy/include/cintcwrapper.h
@@ -7,8 +7,14 @@
 extern "C" {
 #endif // ifdef __cplusplus
 
+    /* misc helpers */
     void* cppyy_load_dictionary(const char* lib_name);
 
+    /* pythonization helpers */
+    cppyy_object_t cppyy_ttree_Branch(
+        void* vtree, const char* branchname, const char* classname,
+        void* addobj, int bufsize, int splitlevel);
+
 #ifdef __cplusplus
 }
 #endif // 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
@@ -59,7 +59,7 @@
             cppscope = W_CPPClass(space, final_name, opaque_handle)
         state.cppscope_cache[name] = cppscope
 
-        cppscope._find_methods()
+        cppscope._build_methods()
         cppscope._find_datamembers()
         return cppscope
 
@@ -91,6 +91,9 @@
 def register_class(space, w_pycppclass):
     w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
     cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
+    # add back-end specific method pythonizations (doing this on the wrapped
+    # class allows simple aliasing of methods)
+    capi.pythonize(space, cppclass.name, w_pycppclass)
     state = space.fromcache(State)
     state.cppclass_registry[cppclass.handle] = w_pycppclass
 
@@ -109,7 +112,10 @@
 
 
 class CPPMethod(object):
-    """ A concrete function after overloading has been resolved """
+    """Dispatcher of methods. Checks the arguments, find the corresponding FFI
+    function if available, makes the call, and returns the wrapped result. It
+    also takes care of offset casting and recycling of known objects through
+    the memory_regulator."""
     _immutable_ = True
     
     def __init__(self, space, containing_scope, method_index, arg_defs, args_required):
@@ -255,6 +261,9 @@
 
 
 class CPPFunction(CPPMethod):
+    """Global (namespaced) function dispatcher. For now, the base class has
+    all the needed functionality, by allowing the C++ this pointer to be null
+    in the call. An optimization is expected there, however."""
     _immutable_ = True
 
     def __repr__(self):
@@ -262,6 +271,9 @@
 
 
 class CPPConstructor(CPPMethod):
+    """Method dispatcher that constructs new objects. In addition to the call,
+    it allocates memory for the newly constructed object and sets ownership
+    to Python."""
     _immutable_ = True
 
     def call(self, cppthis, args_w):
@@ -279,7 +291,27 @@
         return "CPPConstructor: %s" % self.signature()
 
 
+class CPPSetItem(CPPMethod):
+    """Method dispatcher specific to Python's __setitem__ mapped onto C++'s
+    operator[](int). The former function takes an extra argument to assign to
+    the return type of the latter."""
+    _immutable_ = True
+
+    def call(self, cppthis, args_w):
+        end = len(args_w)-1
+        if 0 <= end:
+            w_item = args_w[end]
+            args_w = args_w[:end]
+            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)
+
+
 class W_CPPOverload(Wrappable):
+    """Dispatcher that is actually available at the app-level: it is a
+    collection of (possibly) overloaded methods or functions. It calls these
+    in order and deals with error handling and reporting."""
     _immutable_ = True
 
     def __init__(self, space, containing_scope, functions):
@@ -412,29 +444,43 @@
         assert lltype.typeOf(opaque_handle) == capi.C_SCOPE
         self.handle = opaque_handle
         self.methods = {}
-        # Do not call "self._find_methods()" here, so that a distinction can
+        # Do not call "self._build_methods()" here, so that a distinction can
         #  be made between testing for existence (i.e. existence in the cache
         #  of classes) and actual use. Point being that a class can use itself,
         #  e.g. as a return type or an argument to one of its methods.
 
         self.datamembers = {}
-        # Idem self.methods: a type could hold itself by pointer.
+        # Idem as for self.methods: a type could hold itself by pointer.
 
-    def _find_methods(self):
-        num_methods = capi.c_num_methods(self)
-        args_temp = {}
-        for i in range(num_methods):
-            method_name = capi.c_method_name(self, i)
-            pymethod_name = helper.map_operator_name(
-                    method_name, capi.c_method_num_args(self, i),
-                    capi.c_method_result_type(self, i))
-            if not pymethod_name in self.methods:
-                cppfunction = self._make_cppfunction(i)
-                overload = args_temp.setdefault(pymethod_name, [])
-                overload.append(cppfunction)
-        for name, functions in args_temp.iteritems():
-            overload = W_CPPOverload(self.space, self, functions[:])
-            self.methods[name] = overload
+    def _build_methods(self):
+        assert len(self.methods) == 0
+        methods_temp = {}
+        for i in range(capi.c_num_methods(self)):
+            idx = capi.c_method_index_at(self, i)
+            pyname = helper.map_operator_name(
+                capi.c_method_name(self, idx),
+                capi.c_method_num_args(self, idx),
+                capi.c_method_result_type(self, idx))
+            cppmethod = self._make_cppfunction(pyname, idx)
+            methods_temp.setdefault(pyname, []).append(cppmethod)
+        # the following covers the case where the only kind of operator[](idx)
+        # returns are the ones that produce non-const references; these can be
+        # used for __getitem__ just as much as for __setitem__, though
+        if not "__getitem__" in methods_temp:
+            try:
+                for m in methods_temp["__setitem__"]:
+                    cppmethod = self._make_cppfunction("__getitem__", m.index)
+                    methods_temp.setdefault("__getitem__", []).append(cppmethod)
+            except KeyError:
+                pass          # just means there's no __setitem__ either
+
+        # create the overload methods from the method sets
+        for pyname, methods in methods_temp.iteritems():
+            overload = W_CPPOverload(self.space, self, methods[:])
+            self.methods[pyname] = overload
+
+    def full_name(self):
+        return capi.c_scoped_final_name(self.handle)
 
     def get_method_names(self):
         return self.space.newlist([self.space.wrap(name) for name in self.methods])
@@ -479,6 +525,9 @@
     def __eq__(self, other):
         return self.handle == other.handle
 
+    def __ne__(self, other):
+        return self.handle != other.handle
+
 
 # For now, keep namespaces and classes separate as namespaces are extensible
 # with info from multiple dictionaries and do not need to bother with meta
@@ -488,15 +537,15 @@
     _immutable_ = True
     kind = "namespace"
 
-    def _make_cppfunction(self, method_index):
-        num_args = capi.c_method_num_args(self, method_index)
-        args_required = capi.c_method_req_args(self, method_index)
+    def _make_cppfunction(self, pyname, index):
+        num_args = capi.c_method_num_args(self, index)
+        args_required = capi.c_method_req_args(self, index)
         arg_defs = []
         for i in range(num_args):
-            arg_type = capi.c_method_arg_type(self, method_index, i)
-            arg_dflt = capi.c_method_arg_default(self, method_index, i)
+            arg_type = capi.c_method_arg_type(self, index, i)
+            arg_dflt = capi.c_method_arg_default(self, index, i)
             arg_defs.append((arg_type, arg_dflt))
-        return CPPFunction(self.space, self, method_index, arg_defs, args_required)
+        return CPPFunction(self.space, self, index, arg_defs, args_required)
 
     def _make_datamember(self, dm_name, dm_idx):
         type_name = capi.c_datamember_type(self, dm_idx)
@@ -516,10 +565,10 @@
 
     def find_overload(self, meth_name):
         # TODO: collect all overloads, not just the non-overloaded version
-        meth_idx = capi.c_method_index(self, meth_name)
-        if meth_idx < 0:
+        meth_idx = capi.c_method_index_from_name(self, meth_name)
+        if meth_idx == -1:
             raise self.missing_attribute_error(meth_name)
-        cppfunction = self._make_cppfunction(meth_idx)
+        cppfunction = self._make_cppfunction(meth_name, meth_idx)
         overload = W_CPPOverload(self.space, self, [cppfunction])
         return overload
 
@@ -530,21 +579,38 @@
         datamember = self._make_datamember(dm_name, dm_idx)
         return datamember
 
-    def update(self):
-        self._find_methods()
-        self._find_datamembers()
-
     def is_namespace(self):
         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)):
+            sname = capi.c_scope_name(self, i)
+            if sname: alldir.append(self.space.wrap(sname))
+        allmeth = {}
+        for i in range(capi.c_num_methods(self)):
+            idx = capi.c_method_index_at(self, i)
+            mname = capi.c_method_name(self, idx)
+            if mname: allmeth.setdefault(mname, 0)
+        for m in allmeth.keys():
+            alldir.append(self.space.wrap(m))
+        for i in range(capi.c_num_datamembers(self)):
+            dname = capi.c_datamember_name(self, i)
+            if dname: alldir.append(self.space.wrap(dname))
+        return self.space.newlist(alldir)
+        
+
 W_CPPNamespace.typedef = TypeDef(
     'CPPNamespace',
-    update = interp2app(W_CPPNamespace.update),
     get_method_names = interp2app(W_CPPNamespace.get_method_names),
     get_overload = interp2app(W_CPPNamespace.get_overload, unwrap_spec=['self', str]),
     get_datamember_names = interp2app(W_CPPNamespace.get_datamember_names),
     get_datamember = interp2app(W_CPPNamespace.get_datamember, unwrap_spec=['self', str]),
     is_namespace = interp2app(W_CPPNamespace.is_namespace),
+    __dir__ = interp2app(W_CPPNamespace.ns__dir__),
 )
 W_CPPNamespace.typedef.acceptable_as_base_class = False
 
@@ -553,21 +619,33 @@
     _immutable_ = True
     kind = "class"
 
-    def _make_cppfunction(self, method_index):
-        num_args = capi.c_method_num_args(self, method_index)
-        args_required = capi.c_method_req_args(self, method_index)
+    def __init__(self, space, name, opaque_handle):
+        W_CPPScope.__init__(self, space, name, opaque_handle)
+        self.default_constructor = None
+
+    def _make_cppfunction(self, pyname, index):
+        default_constructor = False
+        num_args = capi.c_method_num_args(self, index)
+        args_required = capi.c_method_req_args(self, index)
         arg_defs = []
         for i in range(num_args):
-            arg_type = capi.c_method_arg_type(self, method_index, i)
-            arg_dflt = capi.c_method_arg_default(self, method_index, i)
+            arg_type = capi.c_method_arg_type(self, index, i)
+            arg_dflt = capi.c_method_arg_default(self, index, i)
             arg_defs.append((arg_type, arg_dflt))
-        if capi.c_is_constructor(self, method_index):
+        if capi.c_is_constructor(self, index):
             cls = CPPConstructor
-        elif capi.c_is_staticmethod(self, method_index):
+            if args_required == 0:
+                default_constructor = True
+        elif capi.c_is_staticmethod(self, index):
             cls = CPPFunction
+        elif pyname == "__setitem__":
+            cls = CPPSetItem
         else:
             cls = CPPMethod
-        return cls(self.space, self, method_index, arg_defs, args_required)
+        cppfunction = cls(self.space, self, index, arg_defs, args_required)
+        if default_constructor:
+            self.default_constructor = cppfunction
+        return cppfunction
 
     def _find_datamembers(self):
         num_datamembers = capi.c_num_datamembers(self)
@@ -581,6 +659,11 @@
             datamember = W_CPPDataMember(self.space, self, type_name, offset, is_static)
             self.datamembers[datamember_name] = datamember
 
+    def construct(self):
+        if self.default_constructor is not None:
+            return self.default_constructor.call(capi.C_NULL_OBJECT, [])
+        raise self.missing_attribute_error("default_constructor")
+
     def find_overload(self, name):
         raise self.missing_attribute_error(name)
 
@@ -698,7 +781,21 @@
 
     def instance__eq__(self, w_other):
         other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
-        iseq = self._rawobject == other._rawobject
+        # get here if no class-specific overloaded operator is available, try to
+        # find a global overload in gbl, in __gnu_cxx (for iterators), or in the
+        # scopes of the argument classes (TODO: implement that last)
+        for name in ["", "__gnu_cxx"]:
+            nss = scope_byname(self.space, name)
+            meth_idx = capi.c_get_global_operator(nss, self.cppclass, other.cppclass, "==")
+            if meth_idx != -1:
+                f = nss._make_cppfunction("operator==", meth_idx)
+                ol = W_CPPOverload(self.space, nss, [f])
+                # TODO: cache this operator
+                return ol.call(self, [self, w_other])
+        
+        # fallback: direct pointer comparison (the class comparison is needed since the
+        # first data member in a struct and the struct have the same address)
+        iseq = (self._rawobject == other._rawobject) and (self.cppclass == other.cppclass)
         return self.space.wrap(iseq)
 
     def instance__ne__(self, w_other):
@@ -765,10 +862,12 @@
         w_pycppclass = state.cppclass_registry[handle]
     except KeyError:
         final_name = capi.c_scoped_final_name(handle)
+        # the callback will cache the class by calling register_class
         w_pycppclass = space.call_function(state.w_clgen_callback, space.wrap(final_name))
     return w_pycppclass
 
 def wrap_new_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, python_owns):
+    rawobject = rffi.cast(capi.C_OBJECT, rawobject)
     if space.is_w(w_pycppclass, space.w_None):
         w_pycppclass = get_pythonized_cppclass(space, cppclass.handle)
     w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
@@ -778,12 +877,14 @@
     return w_cppinstance
 
 def wrap_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, python_owns):
+    rawobject = rffi.cast(capi.C_OBJECT, rawobject)
     obj = memory_regulator.retrieve(rawobject)
-    if obj and obj.cppclass == cppclass:
+    if obj is not None and obj.cppclass is cppclass:
         return obj
     return wrap_new_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, python_owns)
 
 def wrap_cppobject(space, w_pycppclass, cppclass, rawobject, isref, python_owns):
+    rawobject = rffi.cast(capi.C_OBJECT, rawobject)
     if rawobject:
         actual = capi.c_actual_class(cppclass, rawobject)
         if actual != cppclass.handle:
@@ -796,11 +897,13 @@
 
 @unwrap_spec(cppinstance=W_CPPInstance)
 def addressof(space, cppinstance):
-     address = rffi.cast(rffi.LONG, cppinstance.get_rawobject())
-     return space.wrap(address)
+    """Takes a bound C++ instance, returns the raw address."""
+    address = rffi.cast(rffi.LONG, cppinstance.get_rawobject())
+    return space.wrap(address)
 
 @unwrap_spec(address=int, owns=bool)
 def bind_object(space, address, w_pycppclass, owns=False):
+    """Takes an address and a bound C++ class proxy, returns a bound instance."""
     rawobject = rffi.cast(capi.C_OBJECT, address)
     w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
     cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
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
@@ -1,6 +1,6 @@
 # NOT_RPYTHON
 import cppyy
-import types
+import types, sys
 
 
 # For now, keep namespaces and classes separate as namespaces are extensible
@@ -15,7 +15,8 @@
             raise AttributeError("%s object has no attribute '%s'" % (self, name))
 
 class CppyyNamespaceMeta(CppyyScopeMeta):
-    pass
+    def __dir__(cls):
+        return cls._cpp_proxy.__dir__()
 
 class CppyyClass(CppyyScopeMeta):
     pass
@@ -124,6 +125,8 @@
             setattr(pycppns, dm, pydm)
             setattr(metans, dm, pydm)
 
+        modname = pycppns.__name__.replace('::', '.')
+        sys.modules['cppyy.gbl.'+modname] = pycppns
     return pycppns
 
 def _drop_cycles(bases):
@@ -196,8 +199,10 @@
         if cppdm.is_static():
             setattr(metacpp, dm_name, pydm)
 
+    # the call to register will add back-end specific pythonizations and thus
+    # needs to run first, so that the generic pythonizations can use them
+    cppyy._register_class(pycppclass)
     _pythonize(pycppclass)
-    cppyy._register_class(pycppclass)
     return pycppclass
 
 def make_cpptemplatetype(scope, template_name):
@@ -251,7 +256,7 @@
         except AttributeError:
             pass
 
-    if not (pycppitem is None):   # pycppitem could be a bound C++ NULL, so check explicitly for Py_None
+    if pycppitem is not None:      # pycppitem could be a bound C++ NULL, so check explicitly for Py_None
         return pycppitem
 
     raise AttributeError("'%s' has no attribute '%s'" % (str(scope), name))
@@ -318,21 +323,15 @@
             return self
         pyclass.__iadd__ = __iadd__
 
-    # for STL iterators, whose comparison functions live globally for gcc
-    # TODO: this needs to be solved fundamentally for all classes
-    if 'iterator' in pyclass.__name__:
-        if hasattr(gbl, '__gnu_cxx'):
-            if hasattr(gbl.__gnu_cxx, '__eq__'):
-                setattr(pyclass, '__eq__', gbl.__gnu_cxx.__eq__)
-            if hasattr(gbl.__gnu_cxx, '__ne__'):
-                setattr(pyclass, '__ne__', gbl.__gnu_cxx.__ne__)
-
-    # map begin()/end() protocol to iter protocol
-    if hasattr(pyclass, 'begin') and hasattr(pyclass, 'end'):
-        # TODO: make gnu-independent
+    # map begin()/end() protocol to iter protocol on STL(-like) classes, but
+    # not on vector, for which otherwise the user has to make sure that the
+    # global == and != for its iterators are reflected, which is a hassle ...
+    if not 'vector' in pyclass.__name__[:11] and \
+            (hasattr(pyclass, 'begin') and hasattr(pyclass, 'end')):
+        # TODO: check return type of begin() and end() for existence
         def __iter__(self):
             iter = self.begin()
-            while gbl.__gnu_cxx.__ne__(iter, self.end()):
+            while iter != self.end():
                 yield iter.__deref__()
                 iter.__preinc__()
             iter.destruct()
@@ -357,32 +356,35 @@
         pyclass.__eq__ = eq
         pyclass.__str__ = pyclass.c_str
 
-    # TODO: clean this up
-    # fixup lack of __getitem__ if no const return
-    if hasattr(pyclass, '__setitem__') and not hasattr(pyclass, '__getitem__'):
-        pyclass.__getitem__ = pyclass.__setitem__
-
 _loaded_dictionaries = {}
 def load_reflection_info(name):
+    """Takes the name of a library containing reflection info, returns a handle
+    to the loaded library."""
     try:
         return _loaded_dictionaries[name]
     except KeyError:
-        dct = cppyy._load_dictionary(name)
-        _loaded_dictionaries[name] = dct
-        return dct
+        lib = cppyy._load_dictionary(name)
+        _loaded_dictionaries[name] = lib
+        return lib
     
 
 # user interface objects (note the two-step of not calling scope_byname here:
 # creation of global functions may cause the creation of classes in the global
 # namespace, so gbl must exist at that point to cache them)
 gbl = make_cppnamespace(None, "::", None, False)   # global C++ namespace
+gbl.__doc__ = "Global C++ namespace."
+sys.modules['cppyy.gbl'] = gbl
 
 # mostly for the benefit of the CINT backend, which treats std as special
 gbl.std = make_cppnamespace(None, "std", None, False)
+sys.modules['cppyy.gbl.std'] = gbl.std
 
 # user-defined pythonizations interface
 _pythonizations = {}
 def add_pythonization(class_name, callback):
+    """Takes a class name and a callback. The callback should take a single
+    argument, the class proxy, and is called the first time the named class
+    is bound."""
     if not callable(callback):
         raise TypeError("given '%s' object is not callable" % str(callback))
     _pythonizations[class_name] = callback
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -1,8 +1,6 @@
 #include "cppyy.h"
 #include "cintcwrapper.h"
 
-#include "Api.h"
-
 #include "TROOT.h"
 #include "TError.h"
 #include "TList.h"
@@ -16,12 +14,19 @@
 #include "TClass.h"
 #include "TClassEdit.h"
 #include "TClassRef.h"
+#include "TClassTable.h"
 #include "TDataMember.h"
 #include "TFunction.h"
 #include "TGlobal.h"
 #include "TMethod.h"
 #include "TMethodArg.h"
 
+// for pythonization
+#include "TTree.h"
+#include "TBranch.h"
+
+#include "Api.h"
+
 #include <assert.h>
 #include <string.h>
 #include <map>
@@ -30,9 +35,8 @@
 #include <utility>
 
 
-/*  CINT internals (some won't work on Windows) -------------------------- */
+/* ROOT/CINT internals --------------------------------------------------- */
 extern long G__store_struct_offset;
-extern "C" void* G__SetShlHandle(char*);
 extern "C" void G__LockCriticalSection();
 extern "C" void G__UnlockCriticalSection();
 
@@ -65,26 +69,15 @@
 typedef std::map<std::string, ClassRefs_t::size_type> ClassRefIndices_t;
 static ClassRefIndices_t g_classref_indices;
 
-class ClassRefsInit {
-public:
-    ClassRefsInit() {   // setup dummy holders for global and std namespaces
-        assert(g_classrefs.size() == (ClassRefs_t::size_type)GLOBAL_HANDLE);
-        g_classref_indices[""] = (ClassRefs_t::size_type)GLOBAL_HANDLE;
-        g_classrefs.push_back(TClassRef(""));
-        g_classref_indices["std"] = g_classrefs.size();
-        g_classrefs.push_back(TClassRef(""));    // CINT ignores std
-        g_classref_indices["::std"] = g_classrefs.size();
-        g_classrefs.push_back(TClassRef(""));    // id.
-    }
-};
-static ClassRefsInit _classrefs_init;
-
 typedef std::vector<TFunction> GlobalFuncs_t;
 static GlobalFuncs_t g_globalfuncs;
 
 typedef std::vector<TGlobal> GlobalVars_t;
 static GlobalVars_t g_globalvars;
 
+typedef std::vector<G__MethodInfo> InterpretedFuncs_t;
+static InterpretedFuncs_t g_interpreted;
+
 
 /* initialization of the ROOT system (debatable ... ) --------------------- */
 namespace {
@@ -94,12 +87,12 @@
     TCppyyApplication(const char* acn, Int_t* argc, char** argv, Bool_t do_load = kTRUE)
            : TApplication(acn, argc, argv) {
 
-       // Explicitly load libMathCore as CINT will not auto load it when using one
-       // of its globals. Once moved to Cling, which should work correctly, we
-       // can remove this statement.
-       gSystem->Load("libMathCore");
+        // Explicitly load libMathCore as CINT will not auto load it when using
+        // one of its globals. Once moved to Cling, which should work correctly,
+        // we can remove this statement.
+        gSystem->Load("libMathCore");
 
-       if (do_load) {
+        if (do_load) {
             // follow TRint to minimize differences with CINT
             ProcessLine("#include <iostream>", kTRUE);
             ProcessLine("#include <_string>",  kTRUE); // for std::string iostream.
@@ -129,10 +122,30 @@
 class ApplicationStarter {
 public:
     ApplicationStarter() {
+        // setup dummy holders for global and std namespaces
+        assert(g_classrefs.size() == (ClassRefs_t::size_type)GLOBAL_HANDLE);
+        g_classref_indices[""] = (ClassRefs_t::size_type)GLOBAL_HANDLE;
+        g_classrefs.push_back(TClassRef(""));
+        g_classref_indices["std"] = g_classrefs.size();
+        g_classrefs.push_back(TClassRef(""));    // CINT ignores std
+        g_classref_indices["::std"] = g_classrefs.size();
+        g_classrefs.push_back(TClassRef(""));    // id.
+ 
+        // an offset for the interpreted methods
+        g_interpreted.push_back(G__MethodInfo());
+
+        // actual application init, if necessary
         if (!gApplication) {
             int argc = 1;
             char* argv[1]; argv[0] = (char*)appname;
             gApplication = new TCppyyApplication(appname, &argc, argv, kTRUE);
+            if (!gProgName)                  // should have been set by TApplication
+                gSystem->SetProgname(appname);
+        }
+
+        // program name should've been set by TApplication; just in case ...
+        if (!gProgName) {
+            gSystem->SetProgname(appname);
         }
     }
 } _applicationStarter;
@@ -141,6 +154,13 @@
 
 
 /* local helpers ---------------------------------------------------------- */
+static inline const std::string resolve_typedef(const std::string& tname) {
+    G__TypeInfo ti(tname.c_str());
+    if (!ti.IsValid())
+        return tname;
+    return TClassEdit::ShortType(TClassEdit::CleanType(ti.TrueName(), 1).c_str(), 3);
+}
+
 static inline char* cppstring_to_cstring(const std::string& name) {
     char* name_char = (char*)malloc(name.size() + 1);
     strcpy(name_char, name.c_str());
@@ -154,17 +174,17 @@
 }
 
 static inline TClassRef type_from_handle(cppyy_type_t handle) {
+    assert((ClassRefs_t::size_type)handle < g_classrefs.size());
     return g_classrefs[(ClassRefs_t::size_type)handle];
 }
 
-static inline TFunction* type_get_method(cppyy_type_t handle, int method_index) {
+static inline TFunction* type_get_method(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
     if (cr.GetClass())
-        return (TFunction*)cr->GetListOfMethods()->At(method_index);
-    return &g_globalfuncs[method_index];
+        return (TFunction*)cr->GetListOfMethods()->At(idx);
+    return (TFunction*)idx;
 }
 
-
 static inline void fixup_args(G__param* libp) {
     for (int i = 0; i < libp->paran; ++i) {
         libp->para[i].ref = libp->para[i].obj.i;
@@ -194,7 +214,6 @@
             libp->para[i].ref = (long)&libp->para[i].obj.i;
             libp->para[i].type = 'd';
             break;
-
         }
         }
     }
@@ -202,16 +221,58 @@
 
 
 /* name to opaque C++ scope representation -------------------------------- */
+int cppyy_num_scopes(cppyy_scope_t handle) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass()) {
+        /* not supported as CINT does not store classes hierarchically */
+        return 0;
+    }
+    return gClassTable->Classes();
+}
+
+char* cppyy_scope_name(cppyy_scope_t handle, int iscope) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass()) {
+        /* not supported as CINT does not store classes hierarchically */
+        assert(!"scope name lookup not supported on inner scopes");
+        return 0;
+    }
+    std::string name = gClassTable->At(iscope);
+    if (name.find("::") == std::string::npos)
+        return cppstring_to_cstring(name);
+    return cppstring_to_cstring("");
+}
+
 char* cppyy_resolve_name(const char* cppitem_name) {
-    if (strcmp(cppitem_name, "") == 0)
+    std::string tname = cppitem_name;
+
+    // global namespace?
+    if (tname.empty())
         return cppstring_to_cstring(cppitem_name);
-    G__TypeInfo ti(cppitem_name);
-    if (ti.IsValid()) {
-        if (ti.Property() & G__BIT_ISENUM)
-            return cppstring_to_cstring("unsigned int");
-        return cppstring_to_cstring(ti.TrueName());
-    }
-    return cppstring_to_cstring(cppitem_name);
+
+    // special care needed for builtin arrays
+    std::string::size_type pos = tname.rfind("[");
+    G__TypeInfo ti(tname.substr(0, pos).c_str());
+
+    // if invalid (most likely unknown), simply return old name
+    if (!ti.IsValid())
+        return cppstring_to_cstring(cppitem_name);
+
+    // special case treatment of enum types as unsigned int (CINTism)
+    if (ti.Property() & G__BIT_ISENUM)
+        return cppstring_to_cstring("unsigned int");
+
+    // actual typedef resolution; add back array declartion portion, if needed
+    std::string rt = ti.TrueName();
+
+    // builtin STL types have fake typedefs :/
+    G__TypeInfo ti_test(rt.c_str());
+    if (!ti_test.IsValid())
+        return cppstring_to_cstring(cppitem_name);
+
+    if (pos != std::string::npos)
+        rt += tname.substr(pos, std::string::npos);
+    return cppstring_to_cstring(rt);
 }
 
 cppyy_scope_t cppyy_get_scope(const char* scope_name) {
@@ -261,6 +322,7 @@
     return klass;
 }
 
+
 /* memory management ------------------------------------------------------ */
 cppyy_object_t cppyy_allocate(cppyy_type_t handle) {
     TClassRef cr = type_from_handle(handle);
@@ -281,11 +343,25 @@
 static inline G__value cppyy_call_T(cppyy_method_t method,
         cppyy_object_t self, int nargs, void* args) {
 
-    G__InterfaceMethod meth = (G__InterfaceMethod)method;
     G__param* libp = (G__param*)((char*)args - offsetof(G__param, para));
     assert(libp->paran == nargs);
     fixup_args(libp);
 
+    if ((InterpretedFuncs_t::size_type)method < g_interpreted.size()) {
+    // the idea here is that all these low values are invalid memory addresses,
+    // allowing the reuse of method to index the stored bytecodes
+        G__CallFunc callf;
+        callf.SetFunc(g_interpreted[(size_t)method]);
+        G__param p;      // G__param has fixed size; libp is sized to nargs
+        for (int i =0; i<nargs; ++i)
+            p.para[i] = libp->para[i];
+        p.paran = nargs;
+        callf.SetArgs(p);     // will copy p yet again
+        return callf.Execute((void*)self);
+    }
+
+    G__InterfaceMethod meth = (G__InterfaceMethod)method;
+
     G__value result;
     G__setnull(&result);
 
@@ -294,13 +370,13 @@
 
     long index = (long)&method;
     G__CurrentCall(G__SETMEMFUNCENV, 0, &index);
-    
+
     // TODO: access to store_struct_offset won't work on Windows
     long store_struct_offset = G__store_struct_offset;
     if (self)
         G__store_struct_offset = (long)self;
 
-    meth(&result, 0, libp, 0);
+    meth(&result, (char*)0, libp, 0);
     if (self)
         G__store_struct_offset = store_struct_offset;
 
@@ -318,9 +394,9 @@
     cppyy_call_T(method, self, nargs, args);
 }
 
-int cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
     G__value result = cppyy_call_T(method, self, nargs, args);
-    return (bool)G__int(result);
+    return (unsigned char)(bool)G__int(result);
 }
 
 char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -348,9 +424,9 @@
     return G__Longlong(result);
 }
 
-double 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) {
     G__value result = cppyy_call_T(method, self, nargs, args);
-    return G__double(result);
+    return (float)G__double(result);
 }
 
 double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -387,7 +463,7 @@
     return G__int(result);
 }
 
-cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /*handle*/, int /*method_index*/) {
+cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /*handle*/, cppyy_index_t /*idx*/) {
     return (cppyy_methptrgetter_t)NULL;
 }
 
@@ -516,22 +592,15 @@
     if (cr.GetClass() && cr->GetListOfMethods())
         return cr->GetListOfMethods()->GetSize();
     else if (strcmp(cr.GetClassName(), "") == 0) {
-    // NOTE: the updated list of global funcs grows with 5 "G__ateval"'s just
-    // because it is being updated => infinite loop! Apply offset to correct ...
-        static int ateval_offset = 0;
-        TCollection* funcs = gROOT->GetListOfGlobalFunctions(kTRUE);
-        ateval_offset += 5;
-	if (g_globalfuncs.size() <= (GlobalFuncs_t::size_type)funcs->GetSize() - ateval_offset) {
-            g_globalfuncs.clear();
+        if (g_globalfuncs.empty()) {
+            TCollection* funcs = gROOT->GetListOfGlobalFunctions(kTRUE);
 	    g_globalfuncs.reserve(funcs->GetSize());
 
             TIter ifunc(funcs);
 
             TFunction* func = 0;
             while ((func = (TFunction*)ifunc.Next())) {
-                if (strcmp(func->GetName(), "G__ateval") == 0)
-                    ateval_offset += 1;
-                else
+                if (strcmp(func->GetName(), "G__ateval") != 0)
                     g_globalfuncs.push_back(*func);
             }
         }
@@ -540,47 +609,75 @@
     return 0;
 }
 
-char* cppyy_method_name(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+cppyy_index_t cppyy_method_index_at(cppyy_scope_t handle, int imeth) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass())
+        return (cppyy_index_t)imeth;
+    return (cppyy_index_t)&g_globalfuncs[imeth];
+}
+
+cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t handle, const char* name) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass()) {
+        gInterpreter->UpdateListOfMethods(cr.GetClass());
+        int imeth = 0;
+        TFunction* func;
+        TIter next(cr->GetListOfMethods());
+        while ((func = (TFunction*)next())) {
+            if (strcmp(name, func->GetName()) == 0) {
+                if (func->Property() & G__BIT_ISPUBLIC)
+                    return (cppyy_index_t)imeth;
+                return (cppyy_index_t)-1;
+            }
+            ++imeth;
+        }
+    }
+    TFunction* func = gROOT->GetGlobalFunction(name, NULL, kTRUE);
+    if (!func)
+        return (cppyy_index_t)-1;  // (void*)-1 is in kernel space, so invalid
+    int idx = g_globalfuncs.size();
+    g_globalfuncs.push_back(*func);
+    return (cppyy_index_t)func;
+}
+
+
+char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return cppstring_to_cstring(f->GetName());
 }
 
-char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
-    TFunction* f = 0;
+char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    if (cr.GetClass()) {
-        if (cppyy_is_constructor(handle, method_index))
-            return cppstring_to_cstring("constructor");
-        f = (TFunction*)cr->GetListOfMethods()->At(method_index);
-    } else
-        f = &g_globalfuncs[method_index];
+    if (cr.GetClass() && cppyy_is_constructor(handle, idx))
+        return cppstring_to_cstring("constructor");
+    TFunction* f = type_get_method(handle, idx);
     return type_cppstring_to_cstring(f->GetReturnTypeName());
 }
 
-int cppyy_method_num_args(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return f->GetNargs();
 }
 
-int cppyy_method_req_args(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return f->GetNargs() - f->GetNargsOpt();
 }
 
-char* cppyy_method_arg_type(cppyy_scope_t handle, int method_index, int arg_index) {
-    TFunction* f = type_get_method(handle, method_index);
+char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t idx, int arg_index) {
+    TFunction* f = type_get_method(handle, idx);
     TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At(arg_index);
     return type_cppstring_to_cstring(arg->GetFullTypeName());
 }
 
-char* cppyy_method_arg_default(cppyy_scope_t, int, int) {
+char* cppyy_method_arg_default(cppyy_scope_t /*handle*/, cppyy_index_t /*idx*/, int /*arg_index*/) {
     /* unused: libffi does not work with CINT back-end */
     return cppstring_to_cstring("");
 }
 
-char* cppyy_method_signature(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+char* cppyy_method_signature(cppyy_scope_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
+    TFunction* f = type_get_method(handle, idx);
     std::ostringstream sig;
     if (cr.GetClass() && cr->GetClassInfo()
         && strcmp(f->GetName(), ((G__ClassInfo*)cr->GetClassInfo())->Name()) != 0)
@@ -596,46 +693,71 @@
     return cppstring_to_cstring(sig.str());
 }
 
-int cppyy_method_index(cppyy_scope_t handle, const char* name) {
+
+cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    if (cr.GetClass()) {
-        gInterpreter->UpdateListOfMethods(cr.GetClass());
-        int imeth = 0;
-        TFunction* func;
-        TIter next(cr->GetListOfMethods());
-        while ((func = (TFunction*)next())) {
-            if (strcmp(name, func->GetName()) == 0) {
-                if (func->Property() & G__BIT_ISPUBLIC)
-                    return imeth;
-                return -1;
+    TFunction* f = type_get_method(handle, idx);
+    if (cr && cr.GetClass() && !cr->IsLoaded()) {
+        G__ClassInfo* gcl = (G__ClassInfo*)cr->GetClassInfo();
+        if (gcl) {
+            long offset;
+            std::ostringstream sig;
+            int nArgs = f->GetNargs();
+            for (int iarg = 0; iarg < nArgs; ++iarg) {
+                sig << ((TMethodArg*)f->GetListOfMethodArgs()->At(iarg))->GetFullTypeName();
+                if (iarg != nArgs-1) sig << ", ";
             }
-            ++imeth;
+            G__MethodInfo gmi = gcl->GetMethod(
+                f->GetName(), sig.str().c_str(), &offset, G__ClassInfo::ExactMatch);
+            cppyy_method_t method = (cppyy_method_t)g_interpreted.size();
+            g_interpreted.push_back(gmi);
+            return method;
         }
     }
-    TFunction* func = gROOT->GetGlobalFunction(name, NULL, kTRUE);
-    if (!func)
-        return -1;
-    int idx = g_globalfuncs.size();
-    g_globalfuncs.push_back(*func);
-    return idx;
+    cppyy_method_t method = (cppyy_method_t)f->InterfaceMethod();
+    return method;
 }
 
-cppyy_method_t cppyy_get_method(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
-    return (cppyy_method_t)f->InterfaceMethod();
+cppyy_index_t cppyy_get_global_operator(cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op) {
+    TClassRef lccr = type_from_handle(lc);
+    TClassRef rccr = type_from_handle(rc);
+
+    if (!lccr.GetClass() || !rccr.GetClass() || scope != GLOBAL_HANDLE)
+        return (cppyy_index_t)-1;  // (void*)-1 is in kernel space, so invalid as a method handle
+
+    std::string lcname = lccr->GetName();
+    std::string rcname = rccr->GetName();
+
+    std::string opname = "operator";
+    opname += op;
+
+    for (int idx = 0; idx < (int)g_globalfuncs.size(); ++idx) {
+        TFunction* func = &g_globalfuncs[idx];
+        if (func->GetListOfMethodArgs()->GetSize() != 2)
+            continue;
+
+        if (func->GetName() == opname) {
+            if (lcname == resolve_typedef(((TMethodArg*)func->GetListOfMethodArgs()->At(0))->GetTypeName()) &&
+                rcname == resolve_typedef(((TMethodArg*)func->GetListOfMethodArgs()->At(1))->GetTypeName())) {
+                return (cppyy_index_t)func;
+            }
+        }
+    }
+
+    return (cppyy_index_t)-1;
 }
 
 
 /* method properties -----------------------------------------------------  */
-int cppyy_is_constructor(cppyy_type_t handle, int method_index) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(method_index);
+    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
     return strcmp(m->GetName(), ((G__ClassInfo*)cr->GetClassInfo())->Name()) == 0;
 }
 
-int cppyy_is_staticmethod(cppyy_type_t handle, int method_index) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(method_index);
+    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
     return m->Property() & G__BIT_ISSTATIC;
 }
 
@@ -776,16 +898,27 @@
     return (cppyy_object_t)new std::string(*(std::string*)ptr);
 }
 
+void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str) {
+   *((std::string*)ptr) = str;
+}
+
 void cppyy_free_stdstring(cppyy_object_t ptr) {
     delete (std::string*)ptr;
 }
 
-void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str) {
-   *((std::string*)ptr) = str;
-}
 
 void* cppyy_load_dictionary(const char* lib_name) {
     if (0 <= gSystem->Load(lib_name))
         return (void*)1;
     return (void*)0;
 }
+
+
+/* pythonization helpers -------------------------------------------------- */
+cppyy_object_t cppyy_ttree_Branch(void* vtree, const char* branchname, const char* classname,
+        void* addobj, int bufsize, int splitlevel) {
+    // this little song-and-dance is to by-pass the handwritten Branch methods
+    TBranch* b = ((TTree*)vtree)->Bronch(branchname, classname, (void*)&addobj, bufsize, splitlevel);
+    if (b) b->SetObject(addobj);
+    return (cppyy_object_t)b;
+}
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -53,6 +53,17 @@
 
 
 /* name to opaque C++ scope representation -------------------------------- */
+int cppyy_num_scopes(cppyy_scope_t handle) {
+    Reflex::Scope s = scope_from_handle(handle);
+    return s.SubScopeSize();
+}
+
+char* cppyy_scope_name(cppyy_scope_t handle, int iscope) {
+    Reflex::Scope s = scope_from_handle(handle);
+    std::string name = s.SubScopeAt(iscope).Name(Reflex::F);
+    return cppstring_to_cstring(name);
+}
+
 char* cppyy_resolve_name(const char* cppitem_name) {
     Reflex::Scope s = Reflex::Scope::ByName(cppitem_name);
     if (s.IsEnum())
@@ -122,8 +133,8 @@
     return result;
 }
 
-int cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
-    return (int)cppyy_call_T<bool>(method, self, nargs, args);
+unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+    return (unsigned char)cppyy_call_T<bool>(method, self, nargs, args);
 }
 
 char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -146,7 +157,7 @@
     return cppyy_call_T<long long>(method, self, nargs, args);
 }
 
-double 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) {
     return cppyy_call_T<float>(method, self, nargs, args);
 }
 
@@ -188,7 +199,7 @@
     return 0;
 }
 
-cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t handle, int method_index) {
+cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return get_methptr_getter(m);
@@ -271,6 +282,13 @@
 
 int cppyy_num_bases(cppyy_type_t handle) {
     Reflex::Type t = type_from_handle(handle);
+    std::string name = t.Name(Reflex::FINAL|Reflex::SCOPED);
+    if (5 < name.size() && name.substr(0, 5) == "std::") {
+        // special case: STL base classes are usually unnecessary,
+        // so either build all (i.e. if available) or none
+        for (int i=0; i < (int)t.BaseSize(); ++i)
+            if (!t.BaseAt(i)) return 0;
+    }
     return t.BaseSize();
 }
 
@@ -332,7 +350,28 @@
     return s.FunctionMemberSize();
 }
 
-char* cppyy_method_name(cppyy_scope_t handle, int method_index) {
+cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth) {
+    return (cppyy_index_t)imeth;
+}
+
+cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t handle, const char* name) {
+    Reflex::Scope s = scope_from_handle(handle);
+    // the following appears dumb, but the internal storage for Reflex is an
+    // unsorted std::vector anyway, so there's no gain to be had in using the
+    // Scope::FunctionMemberByName() function
+    int num_meth = s.FunctionMemberSize();
+    for (int imeth = 0; imeth < num_meth; ++imeth) {
+        Reflex::Member m = s.FunctionMemberAt(imeth);
+        if (m.Name() == name) {
+            if (m.IsPublic())
+               return (cppyy_index_t)imeth;
+            return (cppyy_index_t)-1;
+        }
+    }
+    return (cppyy_index_t)-1;
+}
+
+char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     std::string name;
@@ -343,7 +382,7 @@
     return cppstring_to_cstring(name);
 }
 
-char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
+char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     if (m.IsConstructor())
@@ -353,19 +392,19 @@
     return cppstring_to_cstring(name);
 }
 
-int cppyy_method_num_args(cppyy_scope_t handle, int method_index) {
+int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.FunctionParameterSize();
 }
 
-int cppyy_method_req_args(cppyy_scope_t handle, int method_index) {
+int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.FunctionParameterSize(true);
 }
 
-char* cppyy_method_arg_type(cppyy_scope_t handle, int method_index, int arg_index) {
+char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type at = m.TypeOf().FunctionParameterAt(arg_index);
@@ -373,14 +412,14 @@
     return cppstring_to_cstring(name);
 }
 
-char* cppyy_method_arg_default(cppyy_scope_t handle, int method_index, int arg_index) {
+char* cppyy_method_arg_default(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     std::string dflt = m.FunctionParameterDefaultAt(arg_index);
     return cppstring_to_cstring(dflt);
 }
 
-char* cppyy_method_signature(cppyy_scope_t handle, int method_index) {
+char* cppyy_method_signature(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type mt = m.TypeOf();
@@ -398,39 +437,53 @@
     return cppstring_to_cstring(sig.str());
 }
 
-int cppyy_method_index(cppyy_scope_t handle, const char* name) {
-    Reflex::Scope s = scope_from_handle(handle);
-    // the following appears dumb, but the internal storage for Reflex is an
-    // unsorted std::vector anyway, so there's no gain to be had in using the
-    // Scope::FunctionMemberByName() function
-    int num_meth = s.FunctionMemberSize();
-    for (int imeth = 0; imeth < num_meth; ++imeth) {
-        Reflex::Member m = s.FunctionMemberAt(imeth);
-        if (m.Name() == name) {
-            if (m.IsPublic())
-                return imeth;
-            return -1;
-        }
-    }
-    return -1;
-}
-
-cppyy_method_t cppyy_get_method(cppyy_scope_t handle, int method_index) {
+cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     assert(m.IsFunctionMember());
     return (cppyy_method_t)m.Stubfunction();
 }
 
+cppyy_method_t cppyy_get_global_operator(cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op) {
+    Reflex::Type lct = type_from_handle(lc);
+    Reflex::Type rct = type_from_handle(rc);
+    Reflex::Scope nss = scope_from_handle(scope);
+
+    if (!lct || !rct || !nss) 
+        return (cppyy_index_t)-1;  // (void*)-1 is in kernel space, so invalid as a method handle
+
+    std::string lcname = lct.Name(Reflex::SCOPED|Reflex::FINAL);
+    std::string rcname = rct.Name(Reflex::SCOPED|Reflex::FINAL);
+
+    std::string opname = "operator";
+    opname += op;
+
+    for (int idx = 0; idx < (int)nss.FunctionMemberSize(); ++idx) {
+        Reflex::Member m = nss.FunctionMemberAt(idx);
+        if (m.FunctionParameterSize() != 2)
+            continue;
+
+        if (m.Name() == opname) {
+            Reflex::Type mt = m.TypeOf();
+            if (lcname == mt.FunctionParameterAt(0).Name(Reflex::SCOPED|Reflex::FINAL) &&
+                rcname == mt.FunctionParameterAt(1).Name(Reflex::SCOPED|Reflex::FINAL)) {
+                return (cppyy_index_t)idx;
+            }
+        }
+    }
+
+    return (cppyy_index_t)-1;  
+}
+
 
 /* method properties -----------------------------------------------------  */
-int cppyy_is_constructor(cppyy_type_t handle, int method_index) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsConstructor();
 }
 
-int cppyy_is_staticmethod(cppyy_type_t handle, int method_index) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsStatic();
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
@@ -1,6 +1,6 @@
 dicts = example01Dict.so datatypesDict.so advancedcppDict.so advancedcpp2Dict.so \
 overloadsDict.so stltypesDict.so operatorsDict.so fragileDict.so crossingDict.so \
-std_streamsDict.so
+std_streamsDict.so iotypesDict.so
 all : $(dicts)
 
 ROOTSYS := ${ROOTSYS}
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
@@ -2,11 +2,20 @@
 
 
 // for testing of default arguments
-defaulter::defaulter(int a, int b, int c ) {
-   m_a = a;
-   m_b = b;
-   m_c = c;
+#define IMPLEMENT_DEFAULTER_CLASS(type, tname)                               \
+tname##_defaulter::tname##_defaulter(type a, type b, type c) {               \
+   m_a = a; m_b = b; m_c = c;                                                \
 }
+IMPLEMENT_DEFAULTER_CLASS(short, short)
+IMPLEMENT_DEFAULTER_CLASS(unsigned short, ushort)
+IMPLEMENT_DEFAULTER_CLASS(int, int)
+IMPLEMENT_DEFAULTER_CLASS(unsigned, uint)
+IMPLEMENT_DEFAULTER_CLASS(long, long)
+IMPLEMENT_DEFAULTER_CLASS(unsigned long, ulong)
+IMPLEMENT_DEFAULTER_CLASS(long long, llong)
+IMPLEMENT_DEFAULTER_CLASS(unsigned long long, ullong)
+IMPLEMENT_DEFAULTER_CLASS(float, float)
+IMPLEMENT_DEFAULTER_CLASS(double, double)
 
 
 // for esoteric inheritance testing
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
@@ -2,13 +2,24 @@
 
 
 //===========================================================================
-class defaulter {                 // for testing of default arguments
-public:
-    defaulter(int a = 11, int b = 22, int c = 33 );
-
-public:
-    int m_a, m_b, m_c;
+#define DECLARE_DEFAULTER_CLASS(type, tname)                                \
+class tname##_defaulter {                                                   \
+public:                                                                     \
+    tname##_defaulter(type a = 11, type b = 22, type c = 33);               \
+                                                                            \
+public:                                                                     \
+    type m_a, m_b, m_c;                                                     \
 };
+DECLARE_DEFAULTER_CLASS(short, short)   // for testing of default arguments
+DECLARE_DEFAULTER_CLASS(unsigned short, ushort)
+DECLARE_DEFAULTER_CLASS(int, int)
+DECLARE_DEFAULTER_CLASS(unsigned, uint)
+DECLARE_DEFAULTER_CLASS(long, long)
+DECLARE_DEFAULTER_CLASS(unsigned long, ulong)
+DECLARE_DEFAULTER_CLASS(long long, llong)
+DECLARE_DEFAULTER_CLASS(unsigned long long, ullong)
+DECLARE_DEFAULTER_CLASS(float, float)
+DECLARE_DEFAULTER_CLASS(double, double)
 
 
 //===========================================================================
@@ -303,6 +314,16 @@
     long gime_address_ptr_ref(void*& obj) {
         return (long)obj;
     }
+
+    static long set_address_ptr_ptr(void** obj) {
+        (*(long**)obj) = (long*)0x4321;
+        return 42;
+    }
+
+    static long set_address_ptr_ref(void*& obj) {
+        obj = (void*)0x1234;
+        return 21;
+    }
 };
 
 
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
@@ -1,6 +1,6 @@
 <lcgdict>
 
-  <class name="defaulter" />
+  <class pattern="*_defaulter" />
 
   <class name="base_class" />
   <class name="derived_class" />
diff --git a/pypy/module/cppyy/test/advancedcpp_LinkDef.h b/pypy/module/cppyy/test/advancedcpp_LinkDef.h
--- a/pypy/module/cppyy/test/advancedcpp_LinkDef.h
+++ b/pypy/module/cppyy/test/advancedcpp_LinkDef.h
@@ -4,7 +4,16 @@
 #pragma link off all classes;
 #pragma link off all functions;
 
-#pragma link C++ class defaulter;
+#pragma link C++ class short_defaulter;
+#pragma link C++ class ushort_defaulter;
+#pragma link C++ class int_defaulter;
+#pragma link C++ class uint_defaulter;
+#pragma link C++ class long_defaulter;
+#pragma link C++ class ulong_defaulter;
+#pragma link C++ class llong_defaulter;
+#pragma link C++ class ullong_defaulter;
+#pragma link C++ class float_defaulter;
+#pragma link C++ class double_defaulter;
 
 #pragma link C++ class base_class;
 #pragma link C++ class derived_class;
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
@@ -1,7 +1,5 @@
 #include "datatypes.h"
 
-#include <iostream>
-
 
 //===========================================================================
 cppyy_test_data::cppyy_test_data() : m_owns_arrays(false)
@@ -21,6 +19,7 @@
     m_double = -77.;
     m_enum   = kNothing;
 
+    m_bool_array2   = new bool[N];
     m_short_array2  = new short[N];
     m_ushort_array2 = new unsigned short[N];
     m_int_array2    = new int[N];
@@ -32,6 +31,8 @@
     m_double_array2 = new double[N];
 
     for (int i = 0; i < N; ++i) {
+        m_bool_array[i]    =  bool(i%2);
+        m_bool_array2[i]   =  bool((i+1)%2);
         m_short_array[i]   =  -1*i;
         m_short_array2[i]  =  -2*i;
         m_ushort_array[i]  =   3u*i;
@@ -66,6 +67,7 @@
 
 void cppyy_test_data::destroy_arrays() {
     if (m_owns_arrays == true) {
+        delete[] m_bool_array2;
         delete[] m_short_array2;
         delete[] m_ushort_array2;
         delete[] m_int_array2;
@@ -96,6 +98,8 @@
 double         cppyy_test_data::get_double() { return m_double; }
 cppyy_test_data::what cppyy_test_data::get_enum() { return m_enum; }
 
+bool*           cppyy_test_data::get_bool_array()    { return m_bool_array; }
+bool*           cppyy_test_data::get_bool_array2()   { return m_bool_array2; }
 short*          cppyy_test_data::get_short_array()   { return m_short_array; }
 short*          cppyy_test_data::get_short_array2()  { return m_short_array2; }
 unsigned short* cppyy_test_data::get_ushort_array()  { return m_ushort_array; }
@@ -151,8 +155,19 @@
 void cppyy_test_data::set_pod_ref(const cppyy_test_pod& rp)    { m_pod = rp; }
 void cppyy_test_data::set_pod_ptrptr_in(cppyy_test_pod** ppp)  { m_pod = **ppp; }
 void cppyy_test_data::set_pod_void_ptrptr_in(void** pp)        { m_pod = **((cppyy_test_pod**)pp); }
-void cppyy_test_data::set_pod_ptrptr_out(cppyy_test_pod** ppp) { *ppp = &m_pod; }
-void cppyy_test_data::set_pod_void_ptrptr_out(void** pp)       { *((cppyy_test_pod**)pp) = &m_pod; }
+void cppyy_test_data::set_pod_ptrptr_out(cppyy_test_pod** ppp) { delete *ppp; *ppp = new cppyy_test_pod(m_pod); }
+void cppyy_test_data::set_pod_void_ptrptr_out(void** pp)       { delete *((cppyy_test_pod**)pp);
+                                                                 *((cppyy_test_pod**)pp) = new cppyy_test_pod(m_pod); }
+
+//- passers -----------------------------------------------------------------
+short*          cppyy_test_data::pass_array(short* a)          { return a; }
+unsigned short* cppyy_test_data::pass_array(unsigned short* a) { return a; }
+int*            cppyy_test_data::pass_array(int* a)            { return a; }
+unsigned int*   cppyy_test_data::pass_array(unsigned int* a)   { return a; }
+long*           cppyy_test_data::pass_array(long* a)           { return a; }
+unsigned long*  cppyy_test_data::pass_array(unsigned long* a)  { return a; }
+float*          cppyy_test_data::pass_array(float* a)          { return a; }
+double*         cppyy_test_data::pass_array(double* a)         { return a; }
 
 char                cppyy_test_data::s_char   = 's';
 unsigned char       cppyy_test_data::s_uchar  = 'u';
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
@@ -15,7 +15,7 @@
     ~cppyy_test_data();
 
 // special cases
-   enum what { kNothing=6, kSomething=111, kLots=42 };
+    enum what { kNothing=6, kSomething=111, kLots=42 };
 
 // helper
     void destroy_arrays();
@@ -36,6 +36,8 @@
     double               get_double();
     what                 get_enum();
 
+    bool*           get_bool_array();
+    bool*           get_bool_array2();
     short*          get_short_array();
     short*          get_short_array2();
     unsigned short* get_ushort_array();
@@ -94,6 +96,25 @@
     void set_pod_ptrptr_out(cppyy_test_pod**);
     void set_pod_void_ptrptr_out(void**);
 
+// passers
+    short*          pass_array(short*);
+    unsigned short* pass_array(unsigned short*);
+    int*            pass_array(int*);
+    unsigned int*   pass_array(unsigned int*);
+    long*           pass_array(long*);
+    unsigned long*  pass_array(unsigned long*);
+    float*          pass_array(float*);
+    double*         pass_array(double*);
+
+    short*          pass_void_array_h(void* a) { return pass_array((short*)a); }
+    unsigned short* pass_void_array_H(void* a) { return pass_array((unsigned short*)a); }
+    int*            pass_void_array_i(void* a) { return pass_array((int*)a); }
+    unsigned int*   pass_void_array_I(void* a) { return pass_array((unsigned int*)a); }
+    long*           pass_void_array_l(void* a) { return pass_array((long*)a); }
+    unsigned long*  pass_void_array_L(void* a) { return pass_array((unsigned long*)a); }
+    float*          pass_void_array_f(void* a) { return pass_array((float*)a); }
+    double*         pass_void_array_d(void* a) { return pass_array((double*)a); }
+
 public:
 // basic types
     bool                 m_bool;
@@ -112,6 +133,8 @@
     what                 m_enum;
 
 // array types
+    bool            m_bool_array[N];
+    bool*           m_bool_array2;
     short           m_short_array[N];
     short*          m_short_array2;
     unsigned short  m_ushort_array[N];
diff --git a/pypy/module/cppyy/test/example01.cxx b/pypy/module/cppyy/test/example01.cxx
--- a/pypy/module/cppyy/test/example01.cxx
+++ b/pypy/module/cppyy/test/example01.cxx
@@ -156,6 +156,8 @@
    return ::globalAddOneToInt(a);
 }
 
+int ns_example01::gMyGlobalInt = 99;
+
 
 // argument passing
 #define typeValueImp(itype, tname)                                            \
diff --git a/pypy/module/cppyy/test/example01.h b/pypy/module/cppyy/test/example01.h
--- a/pypy/module/cppyy/test/example01.h
+++ b/pypy/module/cppyy/test/example01.h
@@ -60,10 +60,11 @@
 };
 
 
-// global functions
+// global functions and data
 int globalAddOneToInt(int a);
 namespace ns_example01 {
     int globalAddOneToInt(int a);
+    extern int gMyGlobalInt;
 }
 
 #define itypeValue(itype, tname) \
@@ -72,6 +73,7 @@
 #define ftypeValue(ftype) \
    ftype ftype##Value(ftype arg0, int argn=0, ftype arg1=1., ftype arg2=2.)
 
+
 // argument passing
 class ArgPasser {        // use a class for now as methptrgetter not
 public:                  // implemented for global functions
diff --git a/pypy/module/cppyy/test/example01.xml b/pypy/module/cppyy/test/example01.xml
--- a/pypy/module/cppyy/test/example01.xml
+++ b/pypy/module/cppyy/test/example01.xml
@@ -11,6 +11,7 @@
 
   <namespace name="ns_example01" />
   <function name="ns_example01::globalAddOneToInt" />
+  <variable name="ns_example01::gMyGlobalInt" />
 
   <class name="ArgPasser" />
 
diff --git a/pypy/module/cppyy/test/example01_LinkDef.h b/pypy/module/cppyy/test/example01_LinkDef.h
--- a/pypy/module/cppyy/test/example01_LinkDef.h
+++ b/pypy/module/cppyy/test/example01_LinkDef.h
@@ -16,4 +16,6 @@
 #pragma link C++ namespace ns_example01;
 #pragma link C++ function ns_example01::globalAddOneToInt(int);
 
+#pragma link C++ variable ns_example01::gMyGlobalInt;
+
 #endif
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
@@ -77,4 +77,14 @@
 
 void fglobal(int, double, char);
 
+namespace nested1 {
+    class A {};
+    namespace nested2 {
+        class A {};
+        namespace nested3 {
+            class A {};
+        } // namespace nested3
+    } // namespace nested2
+} // namespace nested1
+
 } // namespace fragile
diff --git a/pypy/module/cppyy/test/fragile.xml b/pypy/module/cppyy/test/fragile.xml
--- a/pypy/module/cppyy/test/fragile.xml
+++ b/pypy/module/cppyy/test/fragile.xml
@@ -1,8 +1,14 @@
 <lcgdict>
 
   <namespace name="fragile" />
+  <namespace name="fragile::nested1" />
+  <namespace name="fragile::nested1::nested2" />
+  <namespace name="fragile::nested1::nested2::nested3" />
 
   <class pattern="fragile::[A-Z]" />
+  <class name="fragile::nested1::A" />
+  <class name="fragile::nested1::nested2::A" />
+  <class name="fragile::nested1::nested2::nested3::A" />
 
   <variable name="fragile::gI" />
 
diff --git a/pypy/module/cppyy/test/fragile_LinkDef.h b/pypy/module/cppyy/test/fragile_LinkDef.h
--- a/pypy/module/cppyy/test/fragile_LinkDef.h
+++ b/pypy/module/cppyy/test/fragile_LinkDef.h
@@ -5,6 +5,9 @@
 #pragma link off all functions;
 
 #pragma link C++ namespace fragile;
+#pragma link C++ namespace fragile::nested1;
+#pragma link C++ namespace fragile::nested1::nested2;
+#pragma link C++ namespace fragile::nested1::nested2::nested3;
 
 #pragma link C++ class fragile::A;
 #pragma link C++ class fragile::B;
@@ -16,6 +19,9 @@
 #pragma link C++ class fragile::H;
 #pragma link C++ class fragile::I;
 #pragma link C++ class fragile::J;
+#pragma link C++ class fragile::nested1::A;
+#pragma link C++ class fragile::nested1::nested2::A;
+#pragma link C++ class fragile::nested1::nested2::nested3::A;
 
 #pragma link C++ variable fragile::gI;
 
diff --git a/pypy/module/cppyy/test/iotypes.cxx b/pypy/module/cppyy/test/iotypes.cxx
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/iotypes.cxx
@@ -0,0 +1,7 @@
+#include "iotypes.h"
+
+const IO::Floats_t& IO::SomeDataObject::get_floats() { return m_floats; }
+const IO::Tuples_t& IO::SomeDataObject::get_tuples() { return m_tuples; }
+
+void IO::SomeDataObject::add_float(float f) { m_floats.push_back(f); }
+void IO::SomeDataObject::add_tuple(const std::vector<float>& t) { m_tuples.push_back(t); }
diff --git a/pypy/module/cppyy/test/iotypes.h b/pypy/module/cppyy/test/iotypes.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/iotypes.h
@@ -0,0 +1,28 @@
+#include <vector>
+
+namespace IO {
+
+typedef std::vector<float>                Floats_t;
+typedef std::vector<std::vector<float> >  Tuples_t;
+
+class SomeDataObject {
+public:
+   const Floats_t& get_floats();
+   const Tuples_t& get_tuples();
+
+public:
+   void add_float(float f);
+   void add_tuple(const std::vector<float>& t);
+
+private:
+   Floats_t m_floats;
+   Tuples_t m_tuples;
+};
+
+struct SomeDataStruct {
+   Floats_t Floats;
+   char     Label[3];
+   int      NLabel;
+};
+
+} // namespace IO
diff --git a/pypy/module/cppyy/test/iotypes.xml b/pypy/module/cppyy/test/iotypes.xml
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/iotypes.xml
@@ -0,0 +1,3 @@
+<lcgdict>
+<!-- empty -->
+</lcgdict>
diff --git a/pypy/module/cppyy/test/iotypes_LinkDef.h b/pypy/module/cppyy/test/iotypes_LinkDef.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/iotypes_LinkDef.h
@@ -0,0 +1,16 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+using namespace std;
+#pragma link C++ class vector<vector<float> >+;
+#pragma link C++ class vector<vector<float> >::iterator;
+#pragma link C++ class vector<vector<float> >::const_iterator;
+
+#pragma link C++ namespace IO;
+#pragma link C++ class IO::SomeDataObject+;
+#pragma link C++ class IO::SomeDataStruct+;
+
+#endif
diff --git a/pypy/module/cppyy/test/simple_class.C b/pypy/module/cppyy/test/simple_class.C
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/simple_class.C
@@ -0,0 +1,15 @@
+class MySimpleBase {
+public:
+    MySimpleBase() {}
+};
+
+class MySimpleDerived : public MySimpleBase {
+public:
+    MySimpleDerived() { m_data = -42; }
+    int get_data() { return m_data; }
+    void set_data(int data) { m_data = data; }
+public:
+    int m_data;
+};
+
+typedef MySimpleDerived MySimpleDerived_t;
diff --git a/pypy/module/cppyy/test/std_streams.xml b/pypy/module/cppyy/test/std_streams.xml
--- a/pypy/module/cppyy/test/std_streams.xml
+++ b/pypy/module/cppyy/test/std_streams.xml
@@ -4,4 +4,6 @@
   <class name = "std::ios_base"/>
   <class name = "std::basic_ios<char,std::char_traits<char> >"/>
 
+  <variable name="std::cout" />
+
 </lcgdict>
diff --git a/pypy/module/cppyy/test/std_streams_LinkDef.h b/pypy/module/cppyy/test/std_streams_LinkDef.h
--- a/pypy/module/cppyy/test/std_streams_LinkDef.h
+++ b/pypy/module/cppyy/test/std_streams_LinkDef.h
@@ -4,6 +4,4 @@
 #pragma link off all classes;
 #pragma link off all functions;
 
-#pragma link C++ class std::ostream;
-
 #endif
diff --git a/pypy/module/cppyy/test/stltypes.cxx b/pypy/module/cppyy/test/stltypes.cxx
--- a/pypy/module/cppyy/test/stltypes.cxx
+++ b/pypy/module/cppyy/test/stltypes.cxx
@@ -1,9 +1,6 @@
 #include "stltypes.h"
 
-#define STLTYPES_EXPLICIT_INSTANTIATION(STLTYPE, TTYPE)                         \
-template class std::STLTYPE< TTYPE >;                                           \
-template class __gnu_cxx::__normal_iterator<TTYPE*, std::STLTYPE< TTYPE > >;    \
-template class __gnu_cxx::__normal_iterator<const TTYPE*, std::STLTYPE< TTYPE > >;\
+#define STLTYPES_EXPLICIT_INSTANTIATION_WITH_COMPS(STLTYPE, TTYPE)              \
 namespace __gnu_cxx {                                                           \
 template bool operator==(const std::STLTYPE< TTYPE >::iterator&,                \
                          const std::STLTYPE< TTYPE >::iterator&);               \
@@ -11,10 +8,8 @@
                          const std::STLTYPE< TTYPE >::iterator&);               \
 }
 
-
-//- explicit instantiations of used types
-STLTYPES_EXPLICIT_INSTANTIATION(vector, int)
-STLTYPES_EXPLICIT_INSTANTIATION(vector, just_a_class)
+//- explicit instantiations of used comparisons
+STLTYPES_EXPLICIT_INSTANTIATION_WITH_COMPS(vector, int)
 
 //- class with lots of std::string handling
 stringy_class::stringy_class(const char* s) : m_string(s) {}
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
@@ -3,30 +3,50 @@
 #include <string>
 #include <vector>
 
-#define STLTYPES_EXPLICIT_INSTANTIATION_DECL(STLTYPE, TTYPE)                    \
-extern template class std::STLTYPE< TTYPE >;                                    \
-extern template class __gnu_cxx::__normal_iterator<TTYPE*, std::STLTYPE< TTYPE > >;\
-extern template class __gnu_cxx::__normal_iterator<const TTYPE*, std::STLTYPE< TTYPE > >;\
-namespace __gnu_cxx {                                                           \
-extern template bool operator==(const std::STLTYPE< TTYPE >::iterator&,         \
-                         const std::STLTYPE< TTYPE >::iterator&);               \
-extern template bool operator!=(const std::STLTYPE< TTYPE >::iterator&,         \
-                         const std::STLTYPE< TTYPE >::iterator&);               \
-}
-
-
 //- basic example class
 class just_a_class {
 public:
     int m_i;
 };
 
+#define STLTYPE_INSTANTIATION(STLTYPE, TTYPE, N)                             \
+   std::STLTYPE<TTYPE > STLTYPE##_##N;                                       \
+   std::STLTYPE<TTYPE >::iterator STLTYPE##_##N##_i;                         \
+   std::STLTYPE<TTYPE >::const_iterator STLTYPE##_##N##_ci
 
-#ifndef __CINT__
-//- explicit instantiations of used types
-STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, int)
-STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, just_a_class)
-#endif
+//- instantiations of used STL types
+namespace {
+
+    struct _CppyyVectorInstances {
+
+        STLTYPE_INSTANTIATION(vector, int,          1);
+        STLTYPE_INSTANTIATION(vector, float,        2);
+        STLTYPE_INSTANTIATION(vector, double,       3);
+        STLTYPE_INSTANTIATION(vector, just_a_class, 4);
+
+    };
+
+    struct _CppyyListInstances {
+
+        STLTYPE_INSTANTIATION(list, int,          1);
+        STLTYPE_INSTANTIATION(list, float,        2);
+        STLTYPE_INSTANTIATION(list, double,       3);
+
+    };
+
+} // unnamed namespace
+
+#define STLTYPES_EXPLICIT_INSTANTIATION_DECL_COMPS(STLTYPE, TTYPE)           \
+namespace __gnu_cxx {                                                        \
+extern template bool operator==(const std::STLTYPE< TTYPE >::iterator&,      \
+                         const std::STLTYPE< TTYPE >::iterator&);            \
+extern template bool operator!=(const std::STLTYPE< TTYPE >::iterator&,      \
+                         const std::STLTYPE< TTYPE >::iterator&);            \
+}
+
+// comps for int only to allow testing: normal use of vector is looping over a
+// range-checked version of __getitem__
+STLTYPES_EXPLICIT_INSTANTIATION_DECL_COMPS(vector, int)
 
 
 //- class with lots of std::string handling
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
@@ -3,12 +3,17 @@
   <namespace name="std" />
 
   <class pattern="std::vector<*>" />
+  <class pattern="std::vector<*>::iterator" />
+  <class pattern="std::vector<*>::const_iterator" />
+
+  <class pattern="std::list<*>" />
+  <class pattern="std::list<*>::iterator" />
+  <class pattern="std::list<*>::const_iterator" />
+  <class name="std::__detail::_List_node_base" />
+
   <class pattern="__gnu_cxx::__normal_iterator<*>" />
-  <class pattern="__gnu_cxx::new_allocator<*>" />
-  <class pattern="std::_Vector_base<*>" />
-  <class pattern="std::_Vector_base<*>::_Vector_impl" />
-  <class pattern="std::allocator<*>" />
 
+  <!-- the following are for testing, not for iteration -->
   <function name="__gnu_cxx::operator=="/>
   <function name="__gnu_cxx::operator!="/>
 
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
@@ -7,7 +7,7 @@
 currpath = py.path.local(__file__).dirpath()
 test_dct = str(currpath.join("advancedcppDict.so"))
 
-space = gettestobjspace(usemodules=['cppyy'])
+space = gettestobjspace(usemodules=['cppyy', 'array'])
 
 def setup_module(mod):
     if sys.platform == 'win32':
@@ -31,31 +31,42 @@
         """Test usage of default arguments"""
 
         import cppyy
-        defaulter = cppyy.gbl.defaulter
+        def test_defaulter(n, t):
+            defaulter = getattr(cppyy.gbl, '%s_defaulter' % n)
 
-        d = defaulter()
-        assert d.m_a == 11
-        assert d.m_b == 22
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter()
+            assert d.m_a == t(11)
+            assert d.m_b == t(22)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(0)
-        assert d.m_a ==  0
-        assert d.m_b == 22
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter(0)
+            assert d.m_a ==  t(0)
+            assert d.m_b == t(22)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(1, 2)
-        assert d.m_a ==  1
-        assert d.m_b ==  2
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter(1, 2)
+            assert d.m_a ==  t(1)
+            assert d.m_b ==  t(2)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(3, 4, 5)
-        assert d.m_a ==  3
-        assert d.m_b ==  4
-        assert d.m_c ==  5
-        d.destruct()
+            d = defaulter(3, 4, 5)
+            assert d.m_a ==  t(3)
+            assert d.m_b ==  t(4)
+            assert d.m_c ==  t(5)
+            d.destruct()
+        test_defaulter('short', int)
+        test_defaulter('ushort', int)
+        test_defaulter('int', int)
+        test_defaulter('uint', int)
+        test_defaulter('long', long)
+        test_defaulter('ulong', long)
+        test_defaulter('llong', long)
+        test_defaulter('ullong', long)
+        test_defaulter('float', float)
+        test_defaulter('double', float)
 
     def test02_simple_inheritance(self):
         """Test binding of a basic inheritance structure"""
@@ -372,6 +383,20 @@
         assert cppyy.addressof(o) == pp.gime_address_ptr_ptr(o)
         assert cppyy.addressof(o) == pp.gime_address_ptr_ref(o)
 
+        import array
+        addressofo = array.array('l', [cppyy.addressof(o)])
+        assert addressofo.buffer_info()[0] == pp.gime_address_ptr_ptr(addressofo)
+
+        assert 0 == pp.gime_address_ptr(0)
+        assert 0 == pp.gime_address_ptr(None)
+
+        ptr = cppyy.bind_object(0, some_concrete_class)
+        assert cppyy.addressof(ptr) == 0
+        pp.set_address_ptr_ref(ptr)
+        assert cppyy.addressof(ptr) == 0x1234
+        pp.set_address_ptr_ptr(ptr)
+        assert cppyy.addressof(ptr) == 0x4321
+
     def test09_opaque_pointer_assing(self):
         """Test passing around of opaque pointers"""
 
diff --git a/pypy/module/cppyy/test/test_cint.py b/pypy/module/cppyy/test/test_cint.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -0,0 +1,289 @@
+import py, os, sys
+from pypy.conftest import gettestobjspace
+
+# These tests are for the CINT backend only (they exercise ROOT features
+# and classes that are not loaded/available with the Reflex backend). At
+# some point, these tests are likely covered by the CLang/LLVM backend.
+from pypy.module.cppyy import capi
+if capi.identify() != 'CINT':
+    py.test.skip("backend-specific: CINT-only tests")
+
+currpath = py.path.local(__file__).dirpath()
+iotypes_dct = str(currpath.join("iotypesDict.so"))
+
+space = gettestobjspace(usemodules=['cppyy'])
+
+def setup_module(mod):
+    if sys.platform == 'win32':
+        py.test.skip("win32 not supported so far")
+    err = os.system("cd '%s' && make CINT=t iotypesDict.so" % currpath)
+    if err:
+        raise OSError("'make' failed (see stderr)")
+
+class AppTestCINT:
+    def setup_class(cls):
+        cls.space = space
+
+    def test01_globals(self):
+        """Test the availability of ROOT globals"""
+
+        import cppyy
+
+        assert cppyy.gbl.gROOT
+        assert cppyy.gbl.gApplication
+        assert cppyy.gbl.gSystem
+        assert cppyy.gbl.TInterpreter.Instance()           # compiled
+        assert cppyy.gbl.TInterpreter                      # interpreted
+        assert cppyy.gbl.TDirectory.CurrentDirectory()     # compiled
+        assert cppyy.gbl.TDirectory                        # interpreted
+
+    def test02_write_access_to_globals(self):
+        """Test overwritability of ROOT globals"""
+
+        import cppyy
+
+        oldval = cppyy.gbl.gDebug
+        assert oldval != 3
+
+        proxy = cppyy.gbl.__class__.gDebug
+        cppyy.gbl.gDebug = 3
+        assert proxy.__get__(proxy) == 3
+
+        # this is where this test differs from test03_write_access_to_globals
+        # in test_pythonify.py
+        cppyy.gbl.gROOT.ProcessLine('int gDebugCopy = gDebug;')
+        assert cppyy.gbl.gDebugCopy == 3
+
+        cppyy.gbl.gDebug = oldval
+
+    def test03_create_access_to_globals(self):
+        """Test creation and access of new ROOT globals"""
+
+        import cppyy
+
+        cppyy.gbl.gROOT.ProcessLine('double gMyOwnGlobal = 3.1415')
+        assert cppyy.gbl.gMyOwnGlobal == 3.1415
+
+        proxy = cppyy.gbl.__class__.gMyOwnGlobal
+        assert proxy.__get__(proxy) == 3.1415
+
+    def test04_auto_loading(self):
+        """Test auto-loading by retrieving a non-preloaded class"""
+
+        import cppyy
+
+        l = cppyy.gbl.TLorentzVector()
+        assert isinstance(l, cppyy.gbl.TLorentzVector)
+
+    def test05_macro_loading(self):
+        """Test accessibility to macro classes"""
+
+        import cppyy
+
+        loadres = cppyy.gbl.gROOT.LoadMacro('simple_class.C')
+        assert loadres == 0
+
+        base = cppyy.gbl.MySimpleBase
+        simple = cppyy.gbl.MySimpleDerived
+        simple_t = cppyy.gbl.MySimpleDerived_t
+
+        assert issubclass(simple, base)
+        assert simple is simple_t
+
+        c = simple()
+        assert isinstance(c, simple)
+        assert c.m_data == c.get_data()
+
+        c.set_data(13)
+        assert c.m_data == 13
+        assert c.get_data() == 13
+
+
+class AppTestCINTPythonizations:
+    def setup_class(cls):
+        cls.space = space
+
+    def test03_TVector(self):
+        """Test TVector2/3/T behavior"""
+
+        import cppyy, math
+
+        N = 51
+
+        # TVectorF is a typedef of floats
+        v = cppyy.gbl.TVectorF(N)
+        for i in range(N):
+             v[i] = i*i
+
+        assert len(v) == N
+        for j in v:
+             assert round(v[int(math.sqrt(j)+0.5)]-j, 5) == 0.
+
+
+class AppTestCINTTTree:
+    def setup_class(cls):
+        cls.space = space
+        cls.w_N = space.wrap(5)
+        cls.w_M = space.wrap(10)
+        cls.w_fname = space.wrap("test.root")
+        cls.w_tname = space.wrap("test")
+        cls.w_title = space.wrap("test tree")
+        cls.w_iotypes = cls.space.appexec([], """():
+            import cppyy
+            return cppyy.load_reflection_info(%r)""" % (iotypes_dct,))
+
+    def test01_write_stdvector(self):
+        """Test writing of a single branched TTree with an std::vector<double>"""
+
+        from cppyy import gbl               # bootstraps, only needed for tests
+        from cppyy.gbl import TFile, TTree
+        from cppyy.gbl.std import vector
+
+        f = TFile(self.fname, "RECREATE")
+        mytree = TTree(self.tname, self.title)
+        mytree._python_owns = False
+
+        v = vector("double")()
+        raises(TypeError, TTree.Branch, None, "mydata", v.__class__.__name__, v)
+        raises(TypeError, TTree.Branch, v, "mydata", v.__class__.__name__, v)
+
+        mytree.Branch("mydata", v.__class__.__name__, v)
+
+        for i in range(self.N):
+            for j in range(self.M):
+                v.push_back(i*self.M+j)
+            mytree.Fill()
+            v.clear()
+        f.Write()
+        f.Close()
+
+    def test02_read_stdvector(self):
+        """Test reading of a single branched TTree with an std::vector<double>"""
+
+        from cppyy import gbl
+        from cppyy.gbl import TFile
+
+        f = TFile(self.fname)
+        mytree = f.Get(self.tname)
+
+        i = 0
+        for event in mytree:
+            assert len(event.mydata) == self.M
+            for entry in event.mydata:
+                assert i == int(entry)
+                i += 1
+        assert i == self.N * self.M
+
+        f.Close()
+
+    def test03_write_some_data_object(self):
+        """Test writing of a complex data object"""
+
+        from cppyy import gbl
+        from cppyy.gbl import TFile, TTree, IO
+        from cppyy.gbl.IO import SomeDataObject
+
+        f = TFile(self.fname, "RECREATE")
+        mytree = TTree(self.tname, self.title)
+
+        d = SomeDataObject()
+        b = mytree.Branch("data", d)
+        mytree._python_owns = False
+        assert b
+
+        for i in range(self.N):
+            for j in range(self.M):
+                d.add_float(i*self.M+j)
+            d.add_tuple(d.get_floats())
+
+            mytree.Fill()
+
+        f.Write()
+        f.Close()
+
+    def test04_read_some_data_object(self):
+        """Test reading of a complex data object"""
+
+        from cppyy import gbl
+        from cppyy.gbl import TFile
+
+        f = TFile(self.fname)
+        mytree = f.Get(self.tname)
+
+        j = 1
+        for event in mytree:
+            i = 0
+            assert len(event.data.get_floats()) == j*self.M
+            for entry in event.data.get_floats():
+                assert i == int(entry)
+                i += 1
+
+            k = 1
+            assert len(event.data.get_tuples()) == j
+            for mytuple in event.data.get_tuples():
+                i = 0
+                assert len(mytuple) == k*self.M
+                for entry in mytuple:
+                    assert i == int(entry)
+                    i += 1
+                k += 1
+            j += 1
+        assert j-1 == self.N
+        #
+        f.Close()
+
+    def test05_branch_activation(self):
+        """Test of automatic branch activation"""
+
+        from cppyy import gbl               # bootstraps, only needed for tests
+        from cppyy.gbl import TFile, TTree
+        from cppyy.gbl.std import vector
+
+        L = 5
+
+        # writing
+        f = TFile(self.fname, "RECREATE")
+        mytree = TTree(self.tname, self.title)
+        mytree._python_owns = False
+
+        for i in range(L):
+            v = vector("double")()
+            mytree.Branch("mydata_%d"%i, v.__class__.__name__, v)
+            mytree.__dict__["v_%d"%i] = v
+
+        for i in range(self.N):
+            for k in range(L):
+                v = mytree.__dict__["v_%d"%k]
+                for j in range(self.M):
+                    mytree.__dict__["v_%d"%k].push_back(i*self.M+j*L+k)
+            mytree.Fill()
+            for k in range(L):
+                v = mytree.__dict__["v_%d"%k]
+                v.clear()
+        f.Write()
+        f.Close()
+
+        del mytree, f
+        import gc
+        gc.collect()
+
+        # reading
+        f = TFile(self.fname)
+        mytree = f.Get(self.tname)
+
+        # force (initial) disabling of all branches
+        mytree.SetBranchStatus("*",0);
+
+        i = 0
+        for event in mytree:
+            for k in range(L):
+                j = 0
+                data = getattr(mytree, "mydata_%d"%k)
+                assert len(data) == self.M
+                for entry in data:
+                    assert entry == i*self.M+j*L+k
+                    j += 1
+                assert j == self.M
+            i += 1
+        assert i == self.N
+
diff --git a/pypy/module/cppyy/test/test_cppyy.py b/pypy/module/cppyy/test/test_cppyy.py
--- a/pypy/module/cppyy/test/test_cppyy.py
+++ b/pypy/module/cppyy/test/test_cppyy.py
@@ -26,7 +26,7 @@
         func, = adddouble.functions
         assert func.executor is None
         func._setup(None)     # creates executor
-        assert isinstance(func.executor, executor.DoubleExecutor)
+        assert isinstance(func.executor, executor._executors['double'])
         assert func.arg_defs == [("double", "")]
 
 
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
@@ -5,7 +5,7 @@
 currpath = py.path.local(__file__).dirpath()
 test_dct = str(currpath.join("datatypesDict.so"))
 
-space = gettestobjspace(usemodules=['cppyy', 'array'])
+space = gettestobjspace(usemodules=['cppyy', 'array', '_rawffi'])
 
 def setup_module(mod):
     if sys.platform == 'win32':
@@ -63,6 +63,10 @@
         # reding of array types
         for i in range(self.N):
             # reading of integer array types
+            assert c.m_bool_array[i]        ==   bool(i%2)
+            assert c.get_bool_array()[i]    ==   bool(i%2)
+            assert c.m_bool_array2[i]       ==   bool((i+1)%2)
+            assert c.get_bool_array2()[i]   ==   bool((i+1)%2)
             assert c.m_short_array[i]       ==  -1*i
             assert c.get_short_array()[i]   ==  -1*i
             assert c.m_short_array2[i]      ==  -2*i
@@ -194,16 +198,39 @@
 
         c.destruct()
 
-    def test04_respect_privacy(self):
-        """Test that privacy settings are respected"""
+    def test04_array_passing(self):
+        """Test passing of array arguments"""
 
-        import cppyy
+        import cppyy, array, sys
         cppyy_test_data = cppyy.gbl.cppyy_test_data
 
         c = cppyy_test_data()
         assert isinstance(c, cppyy_test_data)
 
-        raises(AttributeError, getattr, c, 'm_owns_arrays')
+        a = range(self.N)
+        # test arrays in mixed order, to give overload resolution a workout
+        for t in ['d', 'i', 'f', 'H', 'I', 'h', 'L', 'l' ]:
+            b = array.array(t, a)
+
+            # typed passing
+            ca = c.pass_array(b)
+            assert type(ca[0]) == type(b[0])
+            assert len(b) == self.N
+            for i in range(self.N):
+                assert ca[i] == b[i]
+
+            # void* passing
+            ca = eval('c.pass_void_array_%s(b)' % t)
+            assert type(ca[0]) == type(b[0])
+            assert len(b) == self.N
+            for i in range(self.N):
+                assert ca[i] == b[i]
+
+        # NULL/None passing (will use short*)
+        assert not c.pass_array(0)
+        raises(Exception, c.pass_array(0).__getitem__, 0)    # raises SegfaultException
+        assert not c.pass_array(None)
+        raises(Exception, c.pass_array(None).__getitem__, 0) # id.
 
         c.destruct()
 
@@ -524,3 +551,38 @@
         assert c.m_pod.m_double == 3.14
         assert p.m_int == 888
         assert p.m_double == 3.14
+
+    def test14_respect_privacy(self):
+        """Test that privacy settings are respected"""
+
+        import cppyy
+        cppyy_test_data = cppyy.gbl.cppyy_test_data
+
+        c = cppyy_test_data()
+        assert isinstance(c, cppyy_test_data)
+
+        raises(AttributeError, getattr, c, 'm_owns_arrays')
+
+        c.destruct()
+
+    def test15_buffer_reshaping(self):
+        """Test usage of buffer sizing"""
+
+        import cppyy
+        cppyy_test_data = cppyy.gbl.cppyy_test_data
+
+        c = cppyy_test_data()
+        for func in ['get_bool_array',   'get_bool_array2',
+                     'get_ushort_array', 'get_ushort_array2',
+                     'get_int_array',    'get_int_array2',
+                     'get_uint_array',   'get_uint_array2',
+                     'get_long_array',   'get_long_array2',
+                     'get_ulong_array',  'get_ulong_array2']:
+            arr = getattr(c, func)()
+            arr = arr.shape.fromaddress(arr.itemaddress(0), self.N)
+            assert len(arr) == self.N
+
+            l = list(arr)
+            for i in range(self.N):
+                assert arr[i] == l[i]
+
diff --git a/pypy/module/cppyy/test/test_fragile.py b/pypy/module/cppyy/test/test_fragile.py
--- a/pypy/module/cppyy/test/test_fragile.py
+++ b/pypy/module/cppyy/test/test_fragile.py
@@ -1,6 +1,7 @@
 import py, os, sys
 from pypy.conftest import gettestobjspace
 
+from pypy.module.cppyy import capi
 
 currpath = py.path.local(__file__).dirpath()
 test_dct = str(currpath.join("fragileDict.so"))
@@ -19,7 +20,8 @@
         cls.space = space
         env = os.environ
         cls.w_test_dct  = space.wrap(test_dct)
-        cls.w_datatypes = cls.space.appexec([], """():
+        cls.w_capi = space.wrap(capi)
+        cls.w_fragile = cls.space.appexec([], """():
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
@@ -194,3 +196,61 @@
 
         f = fragile.fglobal
         assert f.__doc__ == "void fragile::fglobal(int, double, char)"
+
+    def test11_dir(self):
+        """Test __dir__ method"""
+
+        import cppyy
+
+        if self.capi.identify() == 'CINT':   # CINT only support classes on global space
+            members = dir(cppyy.gbl)
+            assert 'TROOT' in members
+            assert 'TSystem' in members
+            assert 'TClass' in members
+            members = dir(cppyy.gbl.fragile)
+        else:
+            members = dir(cppyy.gbl.fragile)
+            assert 'A' in members
+            assert 'B' in members
+            assert 'C' in members
+            assert 'D' in members            # classes
+
+            assert 'nested1' in members          # namespace
+
+        assert 'fglobal' in members          # function
+        assert 'gI'in members                # variable
+
+    def test12_imports(self):
+        """Test ability to import from namespace (or fail with ImportError)"""
+
+        import cppyy
+
+        # TODO: namespaces aren't loaded (and thus not added to sys.modules)
+        # with just the from ... import statement; actual use is needed
+        from cppyy.gbl import fragile
+
+        def fail_import():
+            from cppyy.gbl import does_not_exist
+        raises(ImportError, fail_import)
+
+        from cppyy.gbl.fragile import A, B, C, D
+        assert cppyy.gbl.fragile.A is A
+        assert cppyy.gbl.fragile.B is B
+        assert cppyy.gbl.fragile.C is C
+        assert cppyy.gbl.fragile.D is D
+
+        # according to warnings, can't test "import *" ...
+
+        from cppyy.gbl.fragile import nested1
+        assert cppyy.gbl.fragile.nested1 is nested1
+
+        from cppyy.gbl.fragile.nested1 import A, nested2
+        assert cppyy.gbl.fragile.nested1.A is A
+        assert cppyy.gbl.fragile.nested1.nested2 is nested2
+
+        from cppyy.gbl.fragile.nested1.nested2 import A, nested3
+        assert cppyy.gbl.fragile.nested1.nested2.A is A
+        assert cppyy.gbl.fragile.nested1.nested2.nested3 is nested3
+
+        from cppyy.gbl.fragile.nested1.nested2.nested3 import A
+        assert cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -309,6 +309,20 @@
         assert hasattr(z, 'myint')
         assert z.gime_z_(z)
 
+    def test14_bound_unbound_calls(self):
+        """Test (un)bound method calls"""
+
+        import cppyy
+
+        raises(TypeError, cppyy.gbl.example01.addDataToInt, 1)
+
+        meth = cppyy.gbl.example01.addDataToInt
+        raises(TypeError, meth)
+        raises(TypeError, meth, 1)
+
+        e = cppyy.gbl.example01(2)
+        assert 5 == meth(e, 3)
+
 
 class AppTestPYTHONIFY_UI:
     def setup_class(cls):
@@ -345,3 +359,17 @@
 
         example01_pythonize = 1
         raises(TypeError, cppyy.add_pythonization, 'example01', example01_pythonize)
+
+    def test03_write_access_to_globals(self):
+        """Test overwritability of globals"""
+
+        import cppyy
+
+        oldval = cppyy.gbl.ns_example01.gMyGlobalInt
+        assert oldval == 99
+
+        proxy = cppyy.gbl.ns_example01.__class__.gMyGlobalInt
+        cppyy.gbl.ns_example01.gMyGlobalInt = 3
+        assert proxy.__get__(proxy) == 3
+
+        cppyy.gbl.ns_example01.gMyGlobalInt = oldval
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
@@ -17,15 +17,14 @@
 class AppTestSTLVECTOR:
     def setup_class(cls):
         cls.space = space
-        env = os.environ
         cls.w_N = space.wrap(13)
         cls.w_test_dct  = space.wrap(test_dct)
         cls.w_stlvector = cls.space.appexec([], """():
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
-    def test01_builtin_type_vector_type(self):
-        """Test access to an std::vector<int>"""
+    def test01_builtin_type_vector_types(self):
+        """Test access to std::vector<int>/std::vector<double>"""
 
         import cppyy
 
@@ -34,48 +33,46 @@
 
         assert callable(cppyy.gbl.std.vector)
 
-        tv1 = getattr(cppyy.gbl.std, 'vector<int>')
-        tv2 = cppyy.gbl.std.vector('int')
+        type_info = (
+            ("int",     int),
+            ("float",   "float"),
+            ("double",  "double"),
+        )
 
-        assert tv1 is tv2
+        for c_type, p_type in type_info:
+            tv1 = getattr(cppyy.gbl.std, 'vector<%s>' % c_type)
+            tv2 = cppyy.gbl.std.vector(p_type)
+            assert tv1 is tv2
+            assert tv1.iterator is cppyy.gbl.std.vector(p_type).iterator
 
-        assert cppyy.gbl.std.vector(int).iterator is cppyy.gbl.std.vector(int).iterator
+            #----- 
+            v = tv1(); v += range(self.N)    # default args from Reflex are useless :/
+            if p_type == int:                # only type with == and != reflected in .xml
+                assert v.begin().__eq__(v.begin())
+                assert v.begin() == v.begin()
+                assert v.end() == v.end()
+                assert v.begin() != v.end()
+                assert v.end() != v.begin()
 
-        #-----
-        v = tv1(self.N)
-        # TODO: get the following in order
-        #assert v.begin().__eq__(v.begin())
-        #assert v.begin() == v.begin()
-        #assert v.end() == v.end()
-        #assert v.begin() != v.end()
-        #assert v.end() != v.begin()
+            #-----
+            for i in range(self.N):
+                v[i] = i
+                assert v[i] == i
+                assert v.at(i) == i
 
-        #-----
-        for i in range(self.N):
-          # TODO:
-          #  v[i] = i
-          #  assert v[i] == i
-          #  assert v.at(i) == i
-            pass
+            assert v.size() == self.N
+            assert len(v) == self.N
 
-        assert v.size() == self.N
-        assert len(v) == self.N
-        v.destruct()
+            #-----
+            v = tv1()
+            for i in range(self.N):
+                v.push_back(i)
+                assert v.size() == i+1
+                assert v.at(i) == i
+                assert v[i] == i
 
-        #-----
-        v = tv1()
-        for i in range(self.N):
-            v.push_back(i)
-            assert v.size() == i+1
-            assert v.at(i) == i
-            assert v[i] == i
-
-        return
-
-        assert v.size() == self.N
-        assert len(v) == self.N
-        v.destruct()
-
+            assert v.size() == self.N
+            assert len(v) == self.N
 
     def test02_user_type_vector_type(self):
         """Test access to an std::vector<just_a_class>"""
@@ -207,7 +204,6 @@
 class AppTestSTLSTRING:
     def setup_class(cls):
         cls.space = space
-        env = os.environ
         cls.w_test_dct  = space.wrap(test_dct)
         cls.w_stlstring = cls.space.appexec([], """():
             import cppyy
@@ -282,3 +278,59 @@
         c.set_string1(s)
         assert t0 == c.get_string1()
         assert s == c.get_string1()
+
+
+class AppTestSTLSTRING:
+    def setup_class(cls):
+        cls.space = space
+        cls.w_N = space.wrap(13)
+        cls.w_test_dct  = space.wrap(test_dct)
+        cls.w_stlstring = cls.space.appexec([], """():
+            import cppyy
+            return cppyy.load_reflection_info(%r)""" % (test_dct, ))
+
+    def test01_builtin_list_type(self):
+        """Test access to a list<int>"""
+
+        import cppyy
+        from cppyy.gbl import std
+
+        type_info = (
+            ("int",     int),
+            ("float",   "float"),
+            ("double",  "double"),
+        )
+
+        for c_type, p_type in type_info:
+            tl1 = getattr(std, 'list<%s>' % c_type)
+            tl2 = cppyy.gbl.std.list(p_type)
+            assert tl1 is tl2
+            assert tl1.iterator is cppyy.gbl.std.list(p_type).iterator
+
+            #-----
+            a = tl1()
+            for i in range(self.N):
+                a.push_back( i )
+
+            assert len(a) == self.N
+            assert 11 < self.N
+            assert 11 in a
+
+            #-----
+            ll = list(a)
+            for i in range(self.N):
+                assert ll[i] == i
+
+            for val in a:
+                assert ll[ll.index(val)] == val
+
+    def test02_empty_list_type(self):
+        """Test behavior of empty list<int>"""
+
+        import cppyy
+        from cppyy.gbl import std
+
+        a = std.list(int)()
+        for arg in a:
+           pass
+
diff --git a/pypy/module/cppyy/test/test_streams.py b/pypy/module/cppyy/test/test_streams.py
--- a/pypy/module/cppyy/test/test_streams.py
+++ b/pypy/module/cppyy/test/test_streams.py
@@ -18,14 +18,13 @@
     def setup_class(cls):
         cls.space = space
         env = os.environ
-        cls.w_N = space.wrap(13)
         cls.w_test_dct  = space.wrap(test_dct)
-        cls.w_datatypes = cls.space.appexec([], """():
+        cls.w_streams = cls.space.appexec([], """():
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
     def test01_std_ostream(self):
-        """Test access to an std::vector<int>"""
+        """Test availability of std::ostream"""
 
         import cppyy
 
@@ -34,3 +33,9 @@
 
         assert callable(cppyy.gbl.std.ostream)
 
+    def test02_std_cout(self):
+        """Test access to std::cout"""
+
+        import cppyy
+
+        assert not (cppyy.gbl.std.cout is None)
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
@@ -6,6 +6,9 @@
 from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
 
 from pypy.module.cppyy import interp_cppyy, capi
+# These tests are for the backend that support the fast path only.
+if capi.identify() == 'CINT':
+    py.test.skip("CINT does not support fast path")
 
 # load cpyext early, or its global vars are counted as leaks in the test
 # (note that the module is not otherwise used in the test itself)
@@ -44,6 +47,12 @@
         self.__name__ = name
     def getname(self, space, name):
         return self.name
+class FakeBuffer(FakeBase):
+    typedname = "buffer"
+    def __init__(self, val):
+        self.val = val
+    def get_raw_address(self):
+        raise ValueError("no raw buffer")
 class FakeException(FakeType):
     def __init__(self, name):
         FakeType.__init__(self, name)
@@ -117,6 +126,9 @@
     def interpclass_w(self, w_obj):
         return w_obj
 
+    def buffer_w(self, w_obj):
+        return FakeBuffer(w_obj)
+
     def exception_match(self, typ, sub):
         return typ is sub
 
@@ -143,10 +155,16 @@
     r_longlong_w = int_w
     r_ulonglong_w = uint_w
 
+    def is_(self, w_obj1, w_obj2):
+        return w_obj1 is w_obj2
+
     def isinstance_w(self, w_obj, w_type):
         assert isinstance(w_obj, FakeBase)
         return w_obj.typename == w_type.name
 
+    def is_true(self, w_obj):
+        return not not w_obj
+
     def type(self, w_obj):
         return FakeType("fake")
 
@@ -169,9 +187,6 @@
 
 class TestFastPathJIT(LLJitMixin):
     def _run_zjit(self, method_name):
-        if capi.identify() == 'CINT':   # CINT does not support fast path
-            return
-
         space = FakeSpace()
         drv = jit.JitDriver(greens=[], reds=["i", "inst", "cppmethod"])
         def f():
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -1235,7 +1235,11 @@
             pos += 1
             continue
 
-        if MAXUNICODE < 65536 and 0xD800 <= oc < 0xDC00 and pos + 1 < size:
+        # The following logic is enabled only if MAXUNICODE == 0xffff, or
+        # for testing on top of a host CPython where sys.maxunicode == 0xffff
+        if ((MAXUNICODE < 65536 or
+                (not we_are_translated() and sys.maxunicode < 65536))
+            and 0xD800 <= oc < 0xDC00 and pos + 1 < size):
             # Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes
             pos += 1
             oc2 = ord(s[pos])


More information about the pypy-commit mailing list