[pypy-commit] pypy py3.5: hg merge default

rlamy pypy.commits at gmail.com
Wed Dec 14 14:22:20 EST 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r89063:8454bbf43352
Date: 2016-12-14 18:13 +0000
http://bitbucket.org/pypy/pypy/changeset/8454bbf43352/

Log:	hg merge default

diff too long, truncating to 2000 out of 11892 lines

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -78,3 +78,5 @@
 ^.hypothesis/
 ^release/
 ^rpython/_cache$
+
+pypy/module/cppyy/.+/*\.pcm
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -1,135 +1,36 @@
 cppyy: C++ bindings for PyPy
 ============================
 
-The cppyy module creates, at run-time, Python-side classes and functions for
-C++, by querying a C++ reflection system.
-The default system used is `Reflex`_, which extracts the needed information
-from C++ header files.
-Another current backend is based on `CINT`_, and yet another, more important
-one for the medium- to long-term will be based on `cling`_.
-The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use
-of C++11.
-The work on the cling backend has so far been done only for CPython, but
-bringing it to PyPy is a lot less work than developing it in the first place.
+The cppyy module delivers dynamic Python-C++ bindings.
+It is designed for automation, high performance, scale, interactivity, and
+handling all of modern C++.
+It is based on `Cling`_ which, through `LLVM`_/`clang`_, provides C++
+reflection and interactivity.
+Reflection information is extracted from C++ header files.
+Cppyy itself is built into PyPy (an alternative exists for CPython), but
+it requires a backend, installable through pip, to interface with Cling.
 
-.. _Reflex: https://root.cern.ch/how/how-use-reflex
-.. _CINT: https://root.cern.ch/introduction-cint
-.. _cling: https://root.cern.ch/cling
-.. _llvm: http://llvm.org/
+.. _Cling: https://root.cern.ch/cling
+.. _LLVM: http://llvm.org/
 .. _clang: http://clang.llvm.org/
 
-This document describes the version of cppyy that lives in the main branch of
-PyPy.
-The development of cppyy happens in the "reflex-support" branch.
-
-
-Motivation
-----------
-
-To provide bindings to another language in CPython, you program to a
-generic C-API that exposes many of the interpreter features.
-With PyPy, however, there is no such generic C-API, because several of the
-interpreter features (e.g. the memory model) are pluggable and therefore
-subject to change.
-Furthermore, a generic API does not allow any assumptions about the calls
-into another language, forcing the JIT to behave conservatively around these
-calls and with the objects that cross language boundaries.
-In contrast, cppyy does not expose an API, but expects one to be implemented
-by a backend.
-It makes strong assumptions about the semantics of the API that it uses and
-that in turn allows the JIT to make equally strong assumptions.
-This is possible, because the expected API is only for providing C++ language
-bindings, and does not provide generic programmability.
-
-The cppyy module further offers two features, which result in improved
-performance as well as better functionality and cross-language integration.
-First, cppyy itself is written in RPython and therefore open to optimizations
-by the JIT up until the actual point of call into C++.
-This means for example, that if variables are already unboxed by the JIT, they
-can be passed through directly to C++.
-Second, a backend such as Reflex (and cling far more so) adds dynamic features
-to C++, thus greatly reducing impedance mismatches between the two languages.
-For example, Reflex is dynamic enough to allow writing runtime bindings
-generation in python (as opposed to RPython) and this is used to create very
-natural "pythonizations" of the bound code.
-As another example, cling allows automatic instantiations of templates.
-
-See this description of the `cppyy architecture`_ for further details.
-
-.. _cppyy architecture: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html
-
 
 Installation
 ------------
 
-There are two ways of using cppyy, and the choice depends on how pypy-c was
-built: the backend can be builtin, or dynamically loadable.
-The former has the disadvantage of requiring pypy-c to be linked with external
-C++ libraries (e.g. libReflex.so), but has the advantage of being faster in
-some cases.
-That advantage will disappear over time, however, with improvements in the
-JIT.
-Therefore, this document assumes that the dynamically loadable backend is
-chosen (it is, by default).
-See the :doc:`backend documentation <cppyy_backend>`.
+This assumes PyPy2.7 v5.7 or later; earlier versions use a Reflex-based cppyy
+module, which is no longer supported.
+Both the tooling and user-facing Python codes are very backwards compatible,
+however.
+Further dependencies are cmake (for general build) and Python2.7 (for LLVM).
 
-A standalone version of Reflex that also provides the dynamically loadable
-backend is available for `download`_. Note this is currently the only way to
-get the dynamically loadable backend, so use this first.
+Assuming you have a recent enough version of PyPy installed, use pip to
+complete the installation of cppyy::
 
-That version, as well as any other distribution of Reflex (e.g. the one that
-comes with `ROOT`_, which may be part of your Linux distribution as part of
-the selection of scientific software) will also work for a build with the
-builtin backend.
+ $ pypy-c -m pip install PyPy-cppyy-backend
 
-.. _download: http://cern.ch/wlav/reflex-2014-10-20.tar.bz2
-.. _ROOT: http://root.cern.ch/
-
-Besides Reflex, you probably need a version of `gccxml`_ installed, which is
-most easily provided by the packager of your system.
-If you read up on gccxml, you will probably notice that it is no longer being
-developed and hence will not provide C++11 support.
-That's why the medium term plan is to move to cling.
-Note that gccxml is only needed to generate reflection libraries.
-It is not needed to use them.
-
-.. _gccxml: http://www.gccxml.org
-
-To install the standalone version of Reflex, after download::
-
-    $ tar jxf reflex-2014-10-20.tar.bz2
-    $ cd reflex-2014-10-20
-    $ ./build/autogen
-    $ ./configure <usual set of options such as --prefix>
-    $ make && make install
-
-The usual rules apply: <prefix>/bin needs to be added to the ``PATH`` and
-<prefix>/lib to the ``LD_LIBRARY_PATH`` environment variable.
-For convenience, this document will assume that there is a ``REFLEXHOME``
-variable that points to <prefix>.
-If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal
-to ``ROOTSYS``.
-
-The following is optional, and is only to show how pypy-c can be build
-:doc:`from source <build>`, for example to get at the main development branch of cppyy.
-The :doc:`backend documentation <cppyy_backend>` has more details on the backend-specific
-prerequisites.
-
-Then run the translation to build ``pypy-c``::
-
-    $ hg clone https://bitbucket.org/pypy/pypy
-    $ cd pypy
-    $ hg up reflex-support         # optional
-
-    # This example shows python, but using pypy-c is faster and uses less memory
-    $ python rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
-
-This will build a ``pypy-c`` that includes the cppyy module, and through that,
-Reflex support.
-Of course, if you already have a pre-built version of the ``pypy`` interpreter,
-you can use that for the translation rather than ``python``.
-If not, you may want :ref:`to obtain a binary distribution <prebuilt-pypy>` to speed up the
-translation step.
+The building process may take quite some time as it includes a customized
+version of LLVM as part of Cling.
 
 
 Basic bindings example
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -426,6 +426,8 @@
         make_finalizer_queue(W_Root, self)
         self._code_of_sys_exc_info = None
 
+        self._builtin_functions_by_identifier = {'': None}
+
         # can be overridden to a subclass
         self.initialize()
 
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -257,16 +257,15 @@
     def descr_function_repr(self):
         return self.getrepr(self.space, u'function %s' % self.qualname)
 
-    # delicate
-    _all = {'': None}
 
     def _cleanup_(self):
+        # delicate
         from pypy.interpreter.gateway import BuiltinCode
         if isinstance(self.code, BuiltinCode):
             # we have been seen by other means so rtyping should not choke
             # on us
             identifier = self.code.identifier
-            previous = Function._all.get(identifier, self)
+            previous = self.space._builtin_functions_by_identifier.get(identifier, self)
             assert previous is self, (
                 "duplicate function ids with identifier=%r: %r and %r" % (
                 identifier, previous, self))
@@ -274,10 +273,10 @@
         return False
 
     def add_to_table(self):
-        Function._all[self.code.identifier] = self
+        self.space._builtin_functions_by_identifier[self.code.identifier] = self
 
-    def find(identifier):
-        return Function._all[identifier]
+    def find(space, identifier):
+        return space._builtin_functions_by_identifier[identifier]
     find = staticmethod(find)
 
     def descr_function__reduce__(self, space):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -724,10 +724,10 @@
         return space.newtuple([builtin_code,
                                space.newtuple([space.wrap(self.identifier)])])
 
-    def find(indentifier):
+    @staticmethod
+    def find(space, identifier):
         from pypy.interpreter.function import Function
-        return Function._all[indentifier].code
-    find = staticmethod(find)
+        return Function.find(space, identifier).code
 
     def signature(self):
         return self.sig
diff --git a/pypy/module/_pickle_support/maker.py b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -73,7 +73,7 @@
 def builtin_code(space, identifier):
     from pypy.interpreter import gateway
     try:
-        return gateway.BuiltinCode.find(identifier)
+        return gateway.BuiltinCode.find(space, identifier)
     except KeyError:
         raise oefmt(space.w_RuntimeError,
                     "cannot unpickle builtin code: %s", identifier)
@@ -82,7 +82,7 @@
 def builtin_function(space, identifier):
     from pypy.interpreter import function
     try:
-        return function.Function.find(identifier)
+        return function.Function.find(space, identifier)
     except KeyError:
         raise oefmt(space.w_RuntimeError,
                     "cannot unpickle builtin function: %s", identifier)
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
@@ -14,7 +14,6 @@
         '_set_class_generator'   : 'interp_cppyy.set_class_generator',
         '_set_function_generator': 'interp_cppyy.set_function_generator',
         '_register_class'        : 'interp_cppyy.register_class',
-        '_is_static'             : 'interp_cppyy.is_static',
         '_get_nullptr'           : 'interp_cppyy.get_nullptr',
         'CPPInstanceBase'        : 'interp_cppyy.W_CPPInstance',
         'addressof'              : 'interp_cppyy.addressof',
diff --git a/pypy/module/cppyy/bench/Makefile b/pypy/module/cppyy/bench/Makefile
--- a/pypy/module/cppyy/bench/Makefile
+++ b/pypy/module/cppyy/bench/Makefile
@@ -26,4 +26,4 @@
 
 bench02Dict_reflex.so: bench02.h bench02.cxx bench02.xml
 	$(genreflex) bench02.h $(genreflexflags) --selection=bench02.xml -I$(ROOTSYS)/include
-	g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -lReflex -lHistPainter `root-config --libs` $(cppflags) $(cppflags2)
+	g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -std=c++11 -lHistPainter `root-config --libs` $(cppflags) $(cppflags2)
diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py
--- a/pypy/module/cppyy/capi/builtin_capi.py
+++ b/pypy/module/cppyy/capi/builtin_capi.py
@@ -1,12 +1,11 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import jit
 
-import reflex_capi as backend
-#import cint_capi as backend
+import cling_capi as backend
 
 from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\
-   C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\
-   C_METHPTRGETTER, C_METHPTRGETTER_PTR
+   C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_FUNC_PTR
 
 identify  = backend.identify
 pythonize = backend.pythonize
@@ -52,13 +51,6 @@
     compilation_info=backend.eci)
 def c_get_scope_opaque(space, name):
     return _c_get_scope_opaque(name)
-_c_get_template = rffi.llexternal(
-    "cppyy_get_template",
-    [rffi.CCHARP], C_TYPE,
-    releasegil=ts_reflect,
-    compilation_info=backend.eci)
-def c_get_template(space, name):
-    return _c_get_template(name)
 _c_actual_class = rffi.llexternal(
     "cppyy_actual_class",
     [C_TYPE, C_OBJECT], C_TYPE,
@@ -154,6 +146,13 @@
     compilation_info=backend.eci)
 def c_call_d(space, cppmethod, cppobject, nargs, args):
     return _c_call_d(cppmethod, cppobject, nargs, args)
+_c_call_ld = rffi.llexternal(
+    "cppyy_call_ld",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGDOUBLE,
+    releasegil=ts_call,
+    compilation_info=backend.eci)
+def c_call_ld(space, cppmethod, cppobject, nargs, args):
+    return _c_call_ld(cppmethod, cppobject, nargs, args)
 
 _c_call_r = rffi.llexternal(
     "cppyy_call_r",
@@ -164,11 +163,17 @@
     return _c_call_r(cppmethod, cppobject, nargs, args)
 _c_call_s = rffi.llexternal(
     "cppyy_call_s",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP,
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, rffi.SIZE_TP], rffi.CCHARP,
     releasegil=ts_call,
     compilation_info=backend.eci)
 def c_call_s(space, cppmethod, cppobject, nargs, args):
-    return _c_call_s(cppmethod, cppobject, nargs, args)
+    length = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+    try:
+        cstr = _c_call_s(cppmethod, cppobject, nargs, args, length)
+        cstr_len = intmask(length[0])
+    finally:
+        lltype.free(length, flavor='raw')
+    return cstr, cstr_len
 
 _c_constructor = rffi.llexternal(
     "cppyy_constructor",
@@ -185,15 +190,14 @@
 def c_call_o(space, 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, C_INDEX], C_METHPTRGETTER_PTR,
+_c_get_function_address = rffi.llexternal(
+    "cppyy_get_function_address",
+    [C_SCOPE, C_INDEX], C_FUNC_PTR,
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True,
     random_effects_on_gcobjs=False)
-def c_get_methptr_getter(space, cppscope, index):
-    return _c_get_methptr_getter(cppscope.handle, index)
+def c_get_function_address(space, cppscope, index):
+    return _c_get_function_address(cppscope.handle, index)
 
 # handling of function argument buffer ---------------------------------------
 _c_allocate_function_args = rffi.llexternal(
@@ -215,8 +219,8 @@
     [], rffi.SIZE_T,
     releasegil=ts_memory,
     compilation_info=backend.eci,
-    elidable_function=True,
     random_effects_on_gcobjs=False)
+ at jit.elidable
 def c_function_arg_sizeof(space):
     return _c_function_arg_sizeof()
 _c_function_arg_typeoffset = rffi.llexternal(
@@ -224,8 +228,8 @@
     [], rffi.SIZE_T,
     releasegil=ts_memory,
     compilation_info=backend.eci,
-    elidable_function=True,
     random_effects_on_gcobjs=False)
+ at jit.elidable
 def c_function_arg_typeoffset(space):
     return _c_function_arg_typeoffset()
 
@@ -237,6 +241,20 @@
     compilation_info=backend.eci)
 def c_is_namespace(space, scope):
     return _c_is_namespace(scope)
+_c_is_template = rffi.llexternal(
+    "cppyy_is_template",
+    [rffi.CCHARP], rffi.INT,
+    releasegil=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_template(space, name):
+    return _c_is_template(name)
+_c_is_abstract = rffi.llexternal(
+    "cppyy_is_abstract",
+    [C_SCOPE], rffi.INT,
+    releasegil=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_abstract(space, cpptype):
+    return _c_is_abstract(cpptype)
 _c_is_enum = rffi.llexternal(
     "cppyy_is_enum",
     [rffi.CCHARP], rffi.INT,
@@ -286,9 +304,8 @@
     [C_TYPE, C_TYPE], rffi.INT,
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True,
     random_effects_on_gcobjs=False)
- at jit.elidable_promote('2')
+ at jit.elidable
 def c_is_subtype(space, derived, base):
     if derived == base:
         return 1
@@ -296,12 +313,11 @@
 
 _c_base_offset = rffi.llexternal(
     "cppyy_base_offset",
-    [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T,
+    [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.LONG, # actually ptrdiff_t
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True,
     random_effects_on_gcobjs=False)
- at jit.elidable_promote('1,2,4')
+ at jit.elidable
 def c_base_offset(space, derived, base, address, direction):
     if derived == base:
         return 0
@@ -340,7 +356,7 @@
         i += 1
         py_indices.append(index)
         index = indices[i]
-    c_free(rffi.cast(rffi.VOIDP, indices))   # c_free defined below
+    c_free(space, rffi.cast(rffi.VOIDP, indices))      # c_free defined below
     return py_indices
 
 _c_method_name = rffi.llexternal(
@@ -474,7 +490,7 @@
     return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index))
 _c_datamember_offset = rffi.llexternal(
     "cppyy_datamember_offset",
-    [C_SCOPE, rffi.INT], rffi.SIZE_T,
+    [C_SCOPE, rffi.INT], rffi.LONG, # actually ptrdiff_t
     releasegil=ts_reflect,
     compilation_info=backend.eci)
 def c_datamember_offset(space, cppscope, datamember_index):
@@ -519,27 +535,29 @@
     compilation_info=backend.eci)
 def c_strtoull(space, svalue):
     return _c_strtoull(svalue)
-c_free = rffi.llexternal(
+_c_free = rffi.llexternal(
     "cppyy_free",
     [rffi.VOIDP], lltype.Void,
     releasegil=ts_memory,
     compilation_info=backend.eci)
+def c_free(space, voidp):
+    return _c_free(voidp)
 
 def charp2str_free(space, charp):
     string = rffi.charp2str(charp)
     voidp = rffi.cast(rffi.VOIDP, charp)
-    c_free(voidp)
+    _c_free(voidp)
     return string
 
 _c_charp2stdstring = rffi.llexternal(
     "cppyy_charp2stdstring",
-    [rffi.CCHARP], C_OBJECT,
+    [rffi.CCHARP, rffi.SIZE_T], C_OBJECT,
     releasegil=ts_helper,
     compilation_info=backend.eci)
-def c_charp2stdstring(space, svalue):
-    with rffi.scoped_view_charp(svalue) as charp:
-        result = _c_charp2stdstring(charp)
-    return result
+def c_charp2stdstring(space, pystr, sz):
+    with rffi.scoped_view_charp(pystr) as cstr:
+        cppstr = _c_charp2stdstring(cstr, sz)
+    return cppstr
 _c_stdstring2stdstring = rffi.llexternal(
     "cppyy_stdstring2stdstring",
     [C_OBJECT], C_OBJECT,
@@ -547,3 +565,26 @@
     compilation_info=backend.eci)
 def c_stdstring2stdstring(space, cppobject):
     return _c_stdstring2stdstring(cppobject)
+
+_c_stdvector_valuetype = rffi.llexternal(
+    "cppyy_stdvector_valuetype",
+    [rffi.CCHARP], rffi.CCHARP,
+    releasegil=ts_helper,
+    compilation_info=backend.eci)
+def c_stdvector_valuetype(space, pystr):
+    cstr = rffi.str2charp(pystr)
+    result = _c_stdvector_valuetype(cstr)
+    rffi.free_charp(cstr)
+    if result:
+        return charp2str_free(space, result)
+    return ""
+_c_stdvector_valuesize = rffi.llexternal(
+    "cppyy_stdvector_valuesize",
+    [rffi.CCHARP], rffi.SIZE_T,
+    releasegil=ts_helper,
+    compilation_info=backend.eci)
+def c_stdvector_valuesize(space, pystr):
+    cstr = rffi.str2charp(pystr)
+    result = _c_stdvector_valuesize(cstr)
+    rffi.free_charp(cstr)
+    return result
diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py
--- a/pypy/module/cppyy/capi/capi_types.py
+++ b/pypy/module/cppyy/capi/capi_types.py
@@ -18,5 +18,4 @@
 C_INDEX_ARRAY = rffi.LONGP
 WLAVC_INDEX = rffi.LONG
 
-C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
-C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
+C_FUNC_PTR = rffi.VOIDP
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
deleted file mode 100644
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ /dev/null
@@ -1,437 +0,0 @@
-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 W_Root
-
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rlib import libffi, rdynload
-from rpython.tool.udir import udir
-
-from pypy.module.cppyy.capi.capi_types import C_OBJECT
-
-
-__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary']
-
-pkgpath = py.path.local(__file__).dirpath().join(os.pardir)
-srcpath = pkgpath.join("src")
-incpath = pkgpath.join("include")
-
-if os.environ.get("ROOTSYS"):
-    import commands
-    (stat, incdir) = commands.getstatusoutput("root-config --incdir")
-    if stat != 0:
-        rootincpath = [os.path.join(os.environ["ROOTSYS"], "include"), py.path.local(udir)]
-        rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
-    else:
-        rootincpath = [incdir, py.path.local(udir)]
-        rootlibpath = commands.getoutput("root-config --libdir").split()
-else:
-    rootincpath = [py.path.local(udir)]
-    rootlibpath = []
-
-def identify():
-    return 'CINT'
-
-ts_reflect = True
-ts_call    = True
-ts_memory  = False
-ts_helper  = False
-
-std_string_name = 'string'
-
-# force loading in global mode of core libraries, rather than linking with
-# them as PyPy uses various version of dlopen in various places; note that
-# this isn't going to fly on Windows (note that locking them in objects and
-# calling dlclose in __del__ seems to come too late, so this'll do for now)
-with rffi.scoped_str2charp('libCint.so') as ll_libname:
-    _cintdll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL | rdynload.RTLD_NOW)
-with rffi.scoped_str2charp('libCore.so') as ll_libname:
-    _coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL | rdynload.RTLD_NOW)
-with rffi.scoped_str2charp('libHist.so') as ll_libname:
-    _coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL | rdynload.RTLD_NOW)
-
-eci = ExternalCompilationInfo(
-    separate_module_files=[srcpath.join("cintcwrapper.cxx")],
-    include_dirs=[incpath] + rootincpath,
-    includes=["cintcwrapper.h"],
-    library_dirs=rootlibpath,
-    libraries=["Hist", "Core", "Cint"],
-    use_cpp_linker=True,
-)
-
-_c_load_dictionary = rffi.llexternal(
-    "cppyy_load_dictionary",
-    [rffi.CCHARP], rdynload.DLLHANDLE,
-    releasegil=False,
-    compilation_info=eci)
-
-def c_load_dictionary(name):
-    result = _c_load_dictionary(name)
-    # ignore result: libffi.CDLL(name) either returns a handle to the already
-    # open file, or will fail as well and produce a correctly formatted error
-    return libffi.CDLL(name)
-
-
-# CINT-specific pythonizations ===============================================
-_c_charp2TString = rffi.llexternal(
-    "cppyy_charp2TString",
-    [rffi.CCHARP], C_OBJECT,
-    releasegil=ts_helper,
-    compilation_info=eci)
-def c_charp2TString(space, svalue):
-    with rffi.scoped_view_charp(svalue) as charp:
-        result = _c_charp2TString(charp)
-    return result
-_c_TString2TString = rffi.llexternal(
-    "cppyy_TString2TString",
-    [C_OBJECT], C_OBJECT,
-    releasegil=ts_helper,
-    compilation_info=eci)
-def c_TString2TString(space, cppobject):
-    return _c_TString2TString(cppobject)
-
-def _get_string_data(space, w_obj, m1, m2 = None):
-    from pypy.module.cppyy import interp_cppyy
-    obj = space.interp_w(interp_cppyy.W_CPPInstance, w_obj)
-    w_1 = obj.space.call_method(w_obj, m1)
-    if m2 is None:
-        return w_1
-    return obj.space.call_method(w_1, m2)
-
-### TF1 ----------------------------------------------------------------------
-class State(object):
-    def __init__(self, space):
-        self.tfn_pyfuncs = []
-        self.tfn_callbacks = []
-
-_create_tf1 = rffi.llexternal(
-    "cppyy_create_tf1",
-    [rffi.CCHARP, rffi.ULONG, rffi.DOUBLE, rffi.DOUBLE, rffi.INT], C_OBJECT,
-    releasegil=False,
-    compilation_info=eci)
-
- at unwrap_spec(args_w='args_w')
-def tf1_tf1(space, w_self, args_w):
-    """Pythonized version of TF1 constructor:
-    takes functions and callable objects, and allows a callback into them."""
-
-    from pypy.module.cppyy import interp_cppyy
-    tf1_class = interp_cppyy.scope_byname(space, "TF1")
-
-    # expected signature:
-    #  1. (char* name, pyfunc, double xmin, double xmax, int npar = 0)
-    argc = len(args_w)
-
-    try:
-        if argc < 4 or 5 < argc:
-            raise TypeError("wrong number of arguments")
-
-        # first argument must be a name
-        funcname = space.str_w(args_w[0])
-
-        # last (optional) argument is number of parameters
-        npar = 0
-        if argc == 5: npar = space.int_w(args_w[4])
-
-        # second argument must be a callable python object
-        w_callable = args_w[1]
-        if not space.is_true(space.callable(w_callable)):
-            raise TypeError("2nd argument is not a valid python callable")
-
-        # generate a pointer to function
-        from pypy.module._cffi_backend import newtype, ctypefunc, func
-
-        c_double  = newtype.new_primitive_type(space, 'double')
-        c_doublep = newtype.new_pointer_type(space, c_double)
-
-        # wrap the callable as the signature needs modifying
-        w_ifunc = interp_cppyy.get_interface_func(space, w_callable, npar)
-
-        w_cfunc = ctypefunc.W_CTypeFunc(space, [c_doublep, c_doublep], c_double, False)
-        w_callback = func.callback(space, w_cfunc, w_ifunc, None)
-        funcaddr = rffi.cast(rffi.ULONG, w_callback.get_closure())
-
-        # so far, so good; leaves on issue: CINT is expecting a wrapper, but
-        # we need the overload that takes a function pointer, which is not in
-        # the dictionary, hence this helper:
-        newinst = _create_tf1(space.str_w(args_w[0]), funcaddr,
-                      space.float_w(args_w[2]), space.float_w(args_w[3]), npar)
-
-        # w_self is a null-ptr bound as TF1 
-        from pypy.module.cppyy.interp_cppyy import W_CPPInstance, memory_regulator
-        cppself = space.interp_w(W_CPPInstance, w_self, can_be_None=False)
-        cppself._rawobject = newinst
-        memory_regulator.register(cppself)
-
-        # tie all the life times to the TF1 instance
-        space.setattr(w_self, space.wrap('_callback'), w_callback)
-
-        # by definition for __init__
-        return None
-
-    except (OperationError, TypeError, IndexError) as e:
-        newargs_w = args_w[1:]     # drop class
-
-    # return control back to the original, unpythonized overload
-    ol = tf1_class.get_overload("TF1")
-    return ol.call(None, newargs_w)
-
-### TTree --------------------------------------------------------------------
-_ttree_Branch = rffi.llexternal(
-    "cppyy_ttree_Branch",
-    [rffi.VOIDP, rffi.CCHARP, rffi.CCHARP, rffi.VOIDP, rffi.INT, rffi.INT], C_OBJECT,
-    releasegil=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, TypeError):
-            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, vbranch, branch_class)
-        return w_branch
-    except (OperationError, TypeError, IndexError):
-        pass
-
-    # return control back to the original, unpythonized overload
-    ol = tree_class.get_overload("Branch")
-    return ol.call(w_self, args_w)
-
-def activate_branch(space, w_branch):
-    w_branches = space.call_method(w_branch, "GetListOfBranches")
-    for i in range(space.r_longlong_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")
-
-c_ttree_GetEntry = rffi.llexternal(
-    "cppyy_ttree_GetEntry",
-    [rffi.VOIDP, rffi.LONGLONG], rffi.LONGLONG,
-    releasegil=False,
-    compilation_info=eci)
-
- 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)
-
-    space = tree.space            # holds the class cache in State
-
-    # prevent recursion
-    attr = space.str_w(args_w[0])
-    if attr and attr[0] == '_':
-        raise OperationError(space.w_AttributeError, args_w[0])
-
-    # try the saved cdata (for builtin types)
-    try:
-        w_cdata = space.getattr(w_self, space.wrap('_'+attr))
-        from pypy.module._cffi_backend import cdataobj
-        cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)
-        return cdata.convert_to_object()
-    except OperationError:
-        pass
-
-    # setup branch as a data member and enable it for reading
-    w_branch = space.call_method(w_self, "GetBranch", args_w[0])
-    if not space.is_true(w_branch):
-        raise OperationError(space.w_AttributeError, args_w[0])
-    activate_branch(space, w_branch)
-
-    # figure out from where we're reading
-    entry = space.r_longlong_w(space.call_method(w_self, "GetReadEntry"))
-    if entry == -1:
-        entry = 0
-
-    # setup cache structure
-    w_klassname = space.call_method(w_branch, "GetClassName")
-    if space.is_true(w_klassname):
-        # some instance
-        klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname))
-        w_obj = klass.construct()
-        # 0x10000 = kDeleteObject; reset because we own the object
-        space.call_method(w_branch, "ResetBit", space.wrap(0x10000))
-        space.call_method(w_branch, "SetObject", w_obj)
-        space.call_method(w_branch, "GetEntry", space.wrap(entry))
-        space.setattr(w_self, args_w[0], w_obj)
-        return w_obj
-    else:
-        # builtin data
-        w_leaf = space.call_method(w_self, "GetLeaf", args_w[0])
-        space.call_method(w_branch, "GetEntry", space.wrap(entry))
-
-        # location
-        w_address = space.call_method(w_leaf, "GetValuePointer")
-        buf = space.getarg_w('s*', w_address)
-        from pypy.module._rawffi import buffer
-        assert isinstance(buf, buffer.RawFFIBuffer)
-        address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer)
-
-        # placeholder
-        w_typename = space.call_method(w_leaf, "GetTypeName" )
-        from pypy.module.cppyy import capi
-        typename = capi.c_resolve_name(space, space.str_w(w_typename))
-        if typename == 'bool': typename = '_Bool'
-        w_address = space.call_method(w_leaf, "GetValuePointer")
-        from pypy.module._cffi_backend import cdataobj, newtype
-        cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename))
-
-        # cache result
-        space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata))
-        return space.getattr(w_self, args_w[0])
-
-class W_TTreeIter(W_Root):
-    def __init__(self, space, w_tree):
-        from pypy.module.cppyy import interp_cppyy
-        tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree)
-        self.vtree = rffi.cast(rffi.VOIDP, tree.get_cppthis(tree.cppclass))
-        self.w_tree = w_tree
-
-        self.current  = 0
-        self.maxentry = space.r_longlong_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?
-        c_ttree_GetEntry(self.vtree, 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"
-
-    allfuncs = [
-
-        ### TF1
-        tf1_tf1,
-
-        ### TTree
-        ttree_Branch, ttree_iter, ttree_getattr,
-    ]
-
-    for f in allfuncs:
-        _pythonizations[f.__name__] = space.wrap(interp2app(f))
-
-def _method_alias(space, w_pycppclass, m1, m2):
-    space.setattr(w_pycppclass, space.wrap(m1),
-                  space.getattr(w_pycppclass, space.wrap(m2)))
-
-# callback coming in when app-level bound classes have been created
-def pythonize(space, name, w_pycppclass):
-
-    if name == "TCollection":
-        _method_alias(space, w_pycppclass, "append", "Add")
-        _method_alias(space, w_pycppclass, "__len__", "GetSize")
-
-    elif name == "TF1":
-        space.setattr(w_pycppclass, space.wrap("__init__"), _pythonizations["tf1_tf1"])
-
-    elif name == "TFile":
-        _method_alias(space, w_pycppclass, "__getattr__", "Get")
-
-    elif name == "TObjString":
-        _method_alias(space, w_pycppclass, "__str__", "GetName")
-        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "GetString")
-
-    elif name == "TString":
-        _method_alias(space, w_pycppclass, "__str__", "Data")
-        _method_alias(space, w_pycppclass, "__len__", "Length")
-        _method_alias(space, w_pycppclass, "__cmp__", "CompareTo")
-        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "Data")
-
-    elif name == "TTree":
-        _method_alias(space, w_pycppclass, "_unpythonized_Branch", "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
-        _method_alias(space, w_pycppclass, "__len__", "GetNoElements")
-
-# destruction callback (needs better solution, but this is for CINT
-# only and should not appear outside of ROOT-specific uses)
-from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL
-
- at cpython_api([rffi.VOIDP], lltype.Void, error=CANNOT_FAIL)
-def _Py_cppyy_recursive_remove(space, cppobject):
-    from pypy.module.cppyy.interp_cppyy import memory_regulator
-    from pypy.module.cppyy.capi import C_OBJECT, C_NULL_OBJECT
-
-    obj = memory_regulator.retrieve(rffi.cast(C_OBJECT, cppobject))
-    if obj is not None:
-        memory_regulator.unregister(obj)
-        obj._rawobject = C_NULL_OBJECT
diff --git a/pypy/module/cppyy/capi/cling_capi.py b/pypy/module/cppyy/capi/cling_capi.py
--- a/pypy/module/cppyy/capi/cling_capi.py
+++ b/pypy/module/cppyy/capi/cling_capi.py
@@ -1,8 +1,17 @@
 import py, os
 
+from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
+
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app
+
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem import rffi
-from rpython.rlib import libffi, rdynload
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rarithmetic import intmask
+from rpython.rlib import jit, libffi, rdynload
+
+from pypy.module._rawffi.array import W_ArrayInstance
+from pypy.module.cppyy.capi.capi_types import C_OBJECT
 
 __all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary']
 
@@ -16,7 +25,8 @@
 if os.environ.get("ROOTSYS"):
     if config_stat != 0:     # presumably Reflex-only
         rootincpath = [os.path.join(os.environ["ROOTSYS"], "interpreter/cling/include"),
-                       os.path.join(os.environ["ROOTSYS"], "interpreter/llvm/inst/include")]
+                       os.path.join(os.environ["ROOTSYS"], "interpreter/llvm/inst/include"),
+                       os.path.join(os.environ["ROOTSYS"], "include"),]
         rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
     else:
         rootincpath = [incdir]
@@ -39,13 +49,21 @@
 
 std_string_name = 'std::basic_string<char>'
 
+# force loading (and exposure) of libCore symbols
+with rffi.scoped_str2charp('libCore.so') as ll_libname:
+    _coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL | rdynload.RTLD_NOW)
+
+# require local translator path to pickup common defs
+from rpython.translator import cdir
+translator_c_dir = py.path.local(cdir)
+
 eci = ExternalCompilationInfo(
     separate_module_files=[srcpath.join("clingcwrapper.cxx")],
-    include_dirs=[incpath] + rootincpath,
+    include_dirs=[incpath, translator_c_dir] + rootincpath,
     includes=["clingcwrapper.h"],
     library_dirs=rootlibpath,
     libraries=["Cling"],
-    compile_extra=["-fno-strict-aliasing"],
+    compile_extra=["-fno-strict-aliasing", "-std=c++11"],
     use_cpp_linker=True,
 )
 
@@ -59,11 +77,120 @@
     pch = _c_load_dictionary(name)
     return pch
 
+_c_stdstring2charp = rffi.llexternal(
+    "cppyy_stdstring2charp",
+    [C_OBJECT, rffi.SIZE_TP], rffi.CCHARP,
+    releasegil=ts_helper,
+    compilation_info=eci)
+def c_stdstring2charp(space, cppstr):
+    sz = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+    try:
+        cstr = _c_stdstring2charp(cppstr, sz)
+        cstr_len = intmask(sz[0])
+    finally:
+        lltype.free(sz, flavor='raw')
+    return rffi.charpsize2str(cstr, cstr_len)
 
-# Cling-specific pythonizations
+# TODO: factor these out ...
+# pythonizations
+
+#
+# std::string behavior
+def stdstring_c_str(space, w_self):
+    """Return a python string taking into account \0"""
+
+    from pypy.module.cppyy import interp_cppyy
+    cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
+    return space.wrap(c_stdstring2charp(space, cppstr._rawobject))
+
+#
+# std::vector behavior
+class W_STLVectorIter(W_AbstractSeqIterObject):
+    _immutable_fields_ = ['overload', 'len']#'data', 'converter', 'len', 'stride', 'vector']
+
+    def __init__(self, space, w_vector):
+        W_AbstractSeqIterObject.__init__(self, w_vector)
+        # TODO: this should live in rpythonize.py or something so that the
+        # imports can move to the top w/o getting circles
+        from pypy.module.cppyy import interp_cppyy
+        assert isinstance(w_vector, interp_cppyy.W_CPPInstance)
+        vector = space.interp_w(interp_cppyy.W_CPPInstance, w_vector)
+        self.overload = vector.cppclass.get_overload("__getitem__")
+
+        from pypy.module.cppyy import capi
+        v_type = capi.c_stdvector_valuetype(space, vector.cppclass.name)
+        v_size = capi.c_stdvector_valuesize(space, vector.cppclass.name)
+
+        if not v_type or not v_size:
+            raise NotImplementedError   # fallback on getitem
+
+        w_arr = vector.cppclass.get_overload("data").call(w_vector, [])
+        arr = space.interp_w(W_ArrayInstance, w_arr, can_be_None=True)
+        if not arr:
+            raise OperationError(space.w_StopIteration, space.w_None)
+
+        self.data = rffi.cast(rffi.VOIDP, space.uint_w(arr.getbuffer(space)))
+
+        from pypy.module.cppyy import converter
+        self.converter = converter.get_converter(space, v_type, '')
+        self.len     = space.uint_w(vector.cppclass.get_overload("size").call(w_vector, []))
+        self.stride  = v_size
+
+    def descr_next(self, space):
+        if self.w_seq is None:
+            raise OperationError(space.w_StopIteration, space.w_None)
+        if self.len <= self.index:
+            self.w_seq = None
+            raise OperationError(space.w_StopIteration, space.w_None)
+        try:
+            from pypy.module.cppyy import capi    # TODO: refector
+            offset = capi.direct_ptradd(rffi.cast(C_OBJECT, self.data), self.index*self.stride)
+            w_item = self.converter.from_memory(space, space.w_None, space.w_None, offset)
+        except OperationError as e:
+            self.w_seq = None
+            if not e.match(space, space.w_IndexError):
+                raise
+            raise OperationError(space.w_StopIteration, space.w_None)
+        self.index += 1
+        return w_item
+
+def stdvector_iter(space, w_self):
+    return W_STLVectorIter(space, w_self)
+
+# setup pythonizations for later use at run-time
+_pythonizations = {}
 def register_pythonizations(space):
     "NOT_RPYTHON"
-    pass
+
+    allfuncs = [
+
+        ### std::string
+        stdstring_c_str,
+
+        ### std::vector
+        stdvector_iter,
+
+    ]
+
+    for f in allfuncs:
+        _pythonizations[f.__name__] = space.wrap(interp2app(f))
+
+def _method_alias(space, w_pycppclass, m1, m2):
+    space.setattr(w_pycppclass, space.wrap(m1),
+                  space.getattr(w_pycppclass, space.wrap(m2)))
 
 def pythonize(space, name, w_pycppclass):
-    pass
+    if name == "string":
+        space.setattr(w_pycppclass, space.wrap("c_str"), _pythonizations["stdstring_c_str"])
+        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str")
+        _method_alias(space, w_pycppclass, "__str__",           "c_str")
+
+    if "vector" in name[:11]: # len('std::vector') == 11
+        from pypy.module.cppyy import capi
+        v_type = capi.c_stdvector_valuetype(space, name)
+        if v_type:
+            space.setattr(w_pycppclass, space.wrap("value_type"), space.wrap(v_type))
+        v_size = capi.c_stdvector_valuesize(space, name)
+        if v_size:
+            space.setattr(w_pycppclass, space.wrap("value_size"), space.wrap(v_size))
+        space.setattr(w_pycppclass, space.wrap("__iter__"), _pythonizations["stdvector_iter"])
diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
--- a/pypy/module/cppyy/capi/loadable_capi.py
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -1,14 +1,18 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel
 from rpython.rlib.rarithmetic import r_singlefloat
 from rpython.tool import leakfinder
 
+from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.error import oefmt
 
 from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
+from pypy.module._cffi_backend import newtype
+from pypy.module.cppyy import ffitypes
 
 from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\
-   C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR
+   C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_FUNC_PTR
 
 
 reflection_library = 'libcppyy_backend.so'
@@ -21,11 +25,32 @@
 
 class _Arg:         # poor man's union
     _immutable_ = True
-    def __init__(self, h = 0, l = -1, s = '', vp = rffi.cast(rffi.VOIDP, 0)):
+    def __init__(self, tc, h = 0, l = -1, s = '', p = rffi.cast(rffi.VOIDP, 0)):
+        self.tc      = tc
         self._handle = h
         self._long   = l
         self._string = s
-        self._voidp  = vp
+        self._voidp  = p
+
+class _ArgH(_Arg):
+    _immutable_ = True
+    def __init__(self, val):
+        _Arg.__init__(self, 'h', h = val)
+
+class _ArgL(_Arg):
+    _immutable_ = True
+    def __init__(self, val):
+        _Arg.__init__(self, 'l', l = val)
+
+class _ArgS(_Arg):
+    _immutable_ = True
+    def __init__(self, val):
+        _Arg.__init__(self, 's', s = val)
+
+class _ArgP(_Arg):
+    _immutable_ = True
+    def __init__(self, val):
+        _Arg.__init__(self, 'p', p = val)
 
 # For the loadable CAPI, the calls start and end in RPython. Therefore, the standard
 # _call of W_CTypeFunc, which expects wrapped objects, does not quite work: some
@@ -55,14 +80,18 @@
                 argtype = self.fargs[i]
                 # the following is clumsy, but the data types used as arguments are
                 # very limited, so it'll do for now
-                if isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned):
+                if obj.tc == 'l':
+                    assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned)
                     misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size)
-                elif isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned):
+                elif obj.tc == 'h':
+                    assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned)
                     misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._handle), argtype.size)
-                elif obj._voidp != rffi.cast(rffi.VOIDP, 0):
+                elif obj.tc == 'p':
+                    assert obj._voidp != rffi.cast(rffi.VOIDP, 0)
                     data = rffi.cast(rffi.VOIDPP, data)
                     data[0] = obj._voidp
                 else:    # only other use is sring
+                    assert obj.tc == 's'
                     n = len(obj._string)
                     assert raw_string == rffi.cast(rffi.CCHARP, 0)
                     # XXX could use rffi.get_nonmovingbuffer_final_null()
@@ -89,35 +118,36 @@
         self.library = None
         self.capi_calls = {}
 
-        import pypy.module._cffi_backend.newtype as nt
+        nt = newtype     # module from _cffi_backend
+        state = space.fromcache(ffitypes.State)   # factored out common types
 
         # TODO: the following need to match up with the globally defined C_XYZ low-level
         # types (see capi/__init__.py), but by using strings here, that isn't guaranteed
-        c_opaque_ptr = nt.new_primitive_type(space, 'unsigned long')
+        c_opaque_ptr = state.c_ulong
  
-        c_scope  = c_opaque_ptr
-        c_type   = c_scope
-        c_object = c_opaque_ptr
-        c_method = c_opaque_ptr
-        c_index  = nt.new_primitive_type(space, 'long')
+        c_scope       = c_opaque_ptr
+        c_type        = c_scope
+        c_object      = c_opaque_ptr
+        c_method      = c_opaque_ptr
+        c_index       = state.c_long
+        c_index_array = state.c_voidp
 
-        c_void   = nt.new_void_type(space)
-        c_char   = nt.new_primitive_type(space, 'char')
-        c_uchar  = nt.new_primitive_type(space, 'unsigned char')
-        c_short  = nt.new_primitive_type(space, 'short')
-        c_int    = nt.new_primitive_type(space, 'int')
-        c_long   = nt.new_primitive_type(space, 'long')
-        c_llong  = nt.new_primitive_type(space, 'long long')
-        c_ullong = nt.new_primitive_type(space, 'unsigned long long')
-        c_float  = nt.new_primitive_type(space, 'float')
-        c_double = nt.new_primitive_type(space, 'double')
+        c_void    = state.c_void
+        c_char    = state.c_char
+        c_uchar   = state.c_uchar
+        c_short   = state.c_short
+        c_int     = state.c_int
+        c_long    = state.c_long
+        c_llong   = state.c_llong
+        c_ullong  = state.c_ullong
+        c_float   = state.c_float
+        c_double  = state.c_double
+        c_ldouble = state.c_ldouble
 
-        c_ccharp = nt.new_pointer_type(space, c_char)
-        c_index_array = nt.new_pointer_type(space, c_void)
+        c_ccharp = state.c_ccharp
+        c_voidp  = state.c_voidp
 
-        c_voidp  = nt.new_pointer_type(space, c_void)
         c_size_t = nt.new_primitive_type(space, 'size_t')
-
         c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t')
 
         self.capi_call_ifaces = {
@@ -127,7 +157,6 @@
 
             'resolve_name'             : ([c_ccharp],                 c_ccharp),
             'get_scope'                : ([c_ccharp],                 c_scope),
-            'get_template'             : ([c_ccharp],                 c_type),
             'actual_class'             : ([c_type, c_object],         c_type),
 
             # memory management
@@ -146,14 +175,16 @@
             'call_ll'      : ([c_method, c_object, c_int, c_voidp],   c_llong),
             'call_f'       : ([c_method, c_object, c_int, c_voidp],   c_float),
             'call_d'       : ([c_method, c_object, c_int, c_voidp],   c_double),
+            'call_ld'      : ([c_method, c_object, c_int, c_voidp],   c_ldouble),
 
             'call_r'       : ([c_method, c_object, c_int, c_voidp],   c_voidp),
-            'call_s'       : ([c_method, c_object, c_int, c_voidp],   c_ccharp),
+            # call_s actually takes an size_t* as last parameter, but this will do
+            'call_s'       : ([c_method, c_object, c_int, c_voidp, c_voidp],    c_ccharp),
 
             'constructor'  : ([c_method, c_object, c_int, c_voidp],   c_object),
             'call_o'       : ([c_method, c_object, c_int, c_voidp, c_type],     c_object),
 
-            'get_methptr_getter'       : ([c_scope, c_index],         c_voidp), # TODO: verify
+            'get_function_address'     : ([c_scope, c_index],         c_voidp), # TODO: verify
 
             # handling of function argument buffer
             'allocate_function_args'   : ([c_int],                    c_voidp),
@@ -163,6 +194,8 @@
 
             # scope reflection information
             'is_namespace'             : ([c_scope],                  c_int),
+            'is_template'              : ([c_ccharp],                 c_int),
+            'is_abstract'              : ([c_type],                   c_int),
             'is_enum'                  : ([c_ccharp],                 c_int),
 
             # type/class reflection information
@@ -216,8 +249,14 @@
             'strtoull'                 : ([c_ccharp],                 c_ullong),
             'free'                     : ([c_voidp],                  c_void),
 
-            'charp2stdstring'          : ([c_ccharp],                 c_object),
+            'charp2stdstring'          : ([c_ccharp, c_size_t],       c_object),
+            #stdstring2charp  actually takes an size_t* as last parameter, but this will do
+            'stdstring2charp'          : ([c_object, c_voidp],        c_ccharp),
             'stdstring2stdstring'      : ([c_object],                 c_object),
+
+            'stdvector_valuetype'      : ([c_ccharp],                 c_ccharp),
+            'stdvector_valuesize'      : ([c_ccharp],                 c_size_t),
+
         }
 
         # size/offset are backend-specific but fixed after load
@@ -277,87 +316,99 @@
     ptr = w_cdata.unsafe_escaping_ptr()
     return rffi.cast(rffi.VOIDP, ptr)
 
+def _cdata_to_ccharp(space, w_cdata):
+    ptr = _cdata_to_ptr(space, w_cdata)      # see above ... something better?
+    return rffi.cast(rffi.CCHARP, ptr)
+
 def c_load_dictionary(name):
     return libffi.CDLL(name)
 
 # name to opaque C++ scope representation ------------------------------------
 def c_num_scopes(space, cppscope):
-    return space.int_w(call_capi(space, 'num_scopes', [_Arg(h=cppscope.handle)]))
+    return space.int_w(call_capi(space, 'num_scopes', [_ArgH(cppscope.handle)]))
 def c_scope_name(space, cppscope, iscope):
-    args = [_Arg(h=cppscope.handle), _Arg(l=iscope)]
+    args = [_ArgH(cppscope.handle), _ArgL(iscope)]
     return charp2str_free(space, call_capi(space, 'scope_name', args))
 
 def c_resolve_name(space, name):
-    return charp2str_free(space, call_capi(space, 'resolve_name', [_Arg(s=name)]))
+    return charp2str_free(space, call_capi(space, 'resolve_name', [_ArgS(name)]))
 def c_get_scope_opaque(space, name):
-    return rffi.cast(C_SCOPE, space.uint_w(call_capi(space, 'get_scope', [_Arg(s=name)])))
-def c_get_template(space, name):
-    return rffi.cast(C_TYPE, space.uint_w(call_capi(space, 'get_template', [_Arg(s=name)])))
+    return rffi.cast(C_SCOPE, space.uint_w(call_capi(space, 'get_scope', [_ArgS(name)])))
 def c_actual_class(space, cppclass, cppobj):
-    args = [_Arg(h=cppclass.handle), _Arg(h=cppobj)]
+    args = [_ArgH(cppclass.handle), _ArgH(cppobj)]
     return rffi.cast(C_TYPE, space.uint_w(call_capi(space, 'actual_class', args)))
 
 # memory management ----------------------------------------------------------
 def c_allocate(space, cppclass):
-    return _cdata_to_cobject(space, call_capi(space, 'allocate', [_Arg(h=cppclass.handle)]))
+    return _cdata_to_cobject(space, call_capi(space, 'allocate', [_ArgH(cppclass.handle)]))
 def c_deallocate(space, cppclass, cppobject):
-    call_capi(space, 'deallocate', [_Arg(h=cppclass.handle), _Arg(h=cppobject)])
+    call_capi(space, 'deallocate', [_ArgH(cppclass.handle), _ArgH(cppobject)])
 def c_destruct(space, cppclass, cppobject):
-    call_capi(space, 'destruct', [_Arg(h=cppclass.handle), _Arg(h=cppobject)])
+    call_capi(space, 'destruct', [_ArgH(cppclass.handle), _ArgH(cppobject)])
 
 # method/function dispatching ------------------------------------------------
 def c_call_v(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     call_capi(space, 'call_v', args)
 def c_call_b(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.UCHAR, space.c_uint_w(call_capi(space, 'call_b', args)))
 def c_call_c(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args))[0])
 def c_call_h(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args)))
 def c_call_i(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.INT, space.c_int_w(call_capi(space, 'call_i', args)))
 def c_call_l(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args)))
 def c_call_ll(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.LONGLONG, space.r_longlong_w(call_capi(space, 'call_ll', args)))
 def c_call_f(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.FLOAT, r_singlefloat(space.float_w(call_capi(space, 'call_f', args))))
 def c_call_d(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args)))
+def c_call_ld(space, cppmethod, cppobject, nargs, cargs):
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+    return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
 
 def c_call_r(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return _cdata_to_ptr(space, call_capi(space, 'call_r', args))
 def c_call_s(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
-    return call_capi(space, 'call_s', args)
+    length = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+    try:
+        w_cstr = call_capi(space, 'call_s',
+            [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs),
+             _ArgP(rffi.cast(rffi.VOIDP, length))])
+        cstr_len = intmask(length[0])
+    finally:
+        lltype.free(length, flavor='raw')
+    return _cdata_to_ccharp(space, w_cstr), cstr_len
 
 def c_constructor(space, cppmethod, cppobject, nargs, cargs):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return _cdata_to_cobject(space, call_capi(space, 'constructor', args))
 def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass):
-    args = [_Arg(h=cppmethod), _Arg(h=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(h=cppclass.handle)]
+    args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs), _ArgH(cppclass.handle)]
     return _cdata_to_cobject(space, call_capi(space, 'call_o', args))
 
-def c_get_methptr_getter(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
-    return rffi.cast(C_METHPTRGETTER_PTR,
-        _cdata_to_ptr(space, call_capi(space, 'get_methptr_getter', args)))
+def c_get_function_address(space, cppscope, index):
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
+    return rffi.cast(C_FUNC_PTR,
+        _cdata_to_ptr(space, call_capi(space, 'get_function_address', args)))
 
 # handling of function argument buffer ---------------------------------------
 def c_allocate_function_args(space, size):
-    return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)]))
+    return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_ArgL(size)]))
 def c_deallocate_function_args(space, cargs):
-    call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)])
+    call_capi(space, 'deallocate_function_args', [_ArgP(cargs)])
 def c_function_arg_sizeof(space):
     state = space.fromcache(State)
     return state.c_sizeof_farg
@@ -367,30 +418,34 @@
 
 # scope reflection information -----------------------------------------------
 def c_is_namespace(space, scope):
-    return space.bool_w(call_capi(space, 'is_namespace', [_Arg(h=scope)]))
+    return space.bool_w(call_capi(space, 'is_namespace', [_ArgH(scope)]))
+def c_is_template(space, name):
+    return space.bool_w(call_capi(space, 'is_template', [_ArgS(name)]))
+def c_is_abstract(space, cpptype):
+    return space.bool_w(call_capi(space, 'is_abstract', [_ArgH(cpptype)]))
 def c_is_enum(space, name):
-    return space.bool_w(call_capi(space, 'is_enum', [_Arg(s=name)]))
+    return space.bool_w(call_capi(space, 'is_enum', [_ArgS(name)]))
 
 # type/class reflection information ------------------------------------------
 def c_final_name(space, cpptype):
-    return charp2str_free(space, call_capi(space, 'final_name', [_Arg(h=cpptype)]))
+    return charp2str_free(space, call_capi(space, 'final_name', [_ArgH(cpptype)]))
 def c_scoped_final_name(space, cpptype):
-    return charp2str_free(space, call_capi(space, 'scoped_final_name', [_Arg(h=cpptype)]))
+    return charp2str_free(space, call_capi(space, 'scoped_final_name', [_ArgH(cpptype)]))
 def c_has_complex_hierarchy(space, handle):
-    return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_Arg(h=handle)]))
+    return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_ArgH(handle)]))
 def c_num_bases(space, cppclass):
-    return space.int_w(call_capi(space, 'num_bases', [_Arg(h=cppclass.handle)]))
+    return space.int_w(call_capi(space, 'num_bases', [_ArgH(cppclass.handle)]))
 def c_base_name(space, cppclass, base_index):
-    args = [_Arg(h=cppclass.handle), _Arg(l=base_index)]
+    args = [_ArgH(cppclass.handle), _ArgL(base_index)]
     return charp2str_free(space, call_capi(space, 'base_name', args))
 def c_is_subtype(space, derived, base):
     jit.promote(base)
     if derived == base:
         return bool(1)
-    return space.bool_w(call_capi(space, 'is_subtype', [_Arg(h=derived.handle), _Arg(h=base.handle)]))
+    return space.bool_w(call_capi(space, 'is_subtype', [_ArgH(derived.handle), _ArgH(base.handle)]))
 
 def _c_base_offset(space, derived_h, base_h, address, direction):
-    args = [_Arg(h=derived_h), _Arg(h=base_h), _Arg(h=address), _Arg(l=direction)]
+    args = [_ArgH(derived_h), _ArgH(base_h), _ArgH(address), _ArgL(direction)]
     return _cdata_to_ptrdiff_t(space, call_capi(space, 'base_offset', args))
 def c_base_offset(space, derived, base, address, direction):
     if derived == base:
@@ -401,13 +456,13 @@
 
 # method/function reflection information -------------------------------------
 def c_num_methods(space, cppscope):
-    args = [_Arg(h=cppscope.handle)]
+    args = [_ArgH(cppscope.handle)]
     return space.int_w(call_capi(space, 'num_methods', args))
 def c_method_index_at(space, cppscope, imethod):
-    args = [_Arg(h=cppscope.handle), _Arg(l=imethod)]
+    args = [_ArgH(cppscope.handle), _ArgL(imethod)]
     return space.int_w(call_capi(space, 'method_index_at', args))
 def c_method_indices_from_name(space, cppscope, name):
-    args = [_Arg(h=cppscope.handle), _Arg(s=name)]
+    args = [_ArgH(cppscope.handle), _ArgS(name)]
     indices = rffi.cast(C_INDEX_ARRAY,
                         _cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', args)))
     if not indices:
@@ -423,91 +478,91 @@
     return py_indices
 
 def c_method_name(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return charp2str_free(space, call_capi(space, 'method_name', args))
 def c_method_result_type(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return charp2str_free(space, call_capi(space, 'method_result_type', args))
 def c_method_num_args(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return space.int_w(call_capi(space, 'method_num_args', args))
 def c_method_req_args(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return space.int_w(call_capi(space, 'method_req_args', args))
 def c_method_arg_type(space, cppscope, index, arg_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(arg_index)]
     return charp2str_free(space, call_capi(space, 'method_arg_type', args))
 def c_method_arg_default(space, cppscope, index, arg_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(arg_index)]
     return charp2str_free(space, call_capi(space, 'method_arg_default', args))
 def c_method_signature(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return charp2str_free(space, call_capi(space, 'method_signature', args))
 
 def c_method_is_template(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'method_is_template', args))
 def _c_method_num_template_args(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return space.int_w(call_capi(space, 'method_num_template_args', args)) 
 def c_template_args(space, cppscope, index):
     nargs = _c_method_num_template_args(space, cppscope, index)
-    arg1 = _Arg(h=cppscope.handle)
-    arg2 = _Arg(l=index)
+    arg1 = _ArgH(cppscope.handle)
+    arg2 = _ArgL(index)
     args = [c_resolve_name(space, charp2str_free(space,
-                call_capi(space, 'method_template_arg_name', [arg1, arg2, _Arg(l=iarg)]))
+                call_capi(space, 'method_template_arg_name', [arg1, arg2, _ArgL(iarg)]))
             ) for iarg in range(nargs)]
     return args
 
 def c_get_method(space, cppscope, index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=index)]
+    args = [_ArgH(cppscope.handle), _ArgL(index)]
     return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method', args)))
 def c_get_global_operator(space, nss, lc, rc, op):
     if nss is not None:
-        args = [_Arg(h=nss.handle), _Arg(h=lc.handle), _Arg(h=rc.handle), _Arg(s=op)]
+        args = [_ArgH(nss.handle), _ArgH(lc.handle), _ArgH(rc.handle), _ArgS(op)]
         return rffi.cast(WLAVC_INDEX, space.int_w(call_capi(space, 'get_global_operator', args)))
     return rffi.cast(WLAVC_INDEX, -1)
 
 # method properties ----------------------------------------------------------
 def c_is_constructor(space, cppclass, index):
-    args = [_Arg(h=cppclass.handle), _Arg(l=index)]
+    args = [_ArgH(cppclass.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'is_constructor', args))
 def c_is_staticmethod(space, cppclass, index):
-    args = [_Arg(h=cppclass.handle), _Arg(l=index)]
+    args = [_ArgH(cppclass.handle), _ArgL(index)]
     return space.bool_w(call_capi(space, 'is_staticmethod', args))
 
 # data member reflection information -----------------------------------------
 def c_num_datamembers(space, cppscope):
-    return space.int_w(call_capi(space, 'num_datamembers', [_Arg(h=cppscope.handle)]))
+    return space.int_w(call_capi(space, 'num_datamembers', [_ArgH(cppscope.handle)]))
 def c_datamember_name(space, cppscope, datamember_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=datamember_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return charp2str_free(space, call_capi(space, 'datamember_name', args))
 def c_datamember_type(space, cppscope, datamember_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=datamember_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return  charp2str_free(space, call_capi(space, 'datamember_type', args))
 def c_datamember_offset(space, cppscope, datamember_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=datamember_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return _cdata_to_ptrdiff_t(space, call_capi(space, 'datamember_offset', args))
 
 def c_datamember_index(space, cppscope, name):
-    args = [_Arg(h=cppscope.handle), _Arg(s=name)]
+    args = [_ArgH(cppscope.handle), _ArgS(name)]
     return space.int_w(call_capi(space, 'datamember_index', args))
 
 # data member properties -----------------------------------------------------
 def c_is_publicdata(space, cppscope, datamember_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=datamember_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return space.bool_w(call_capi(space, 'is_publicdata', args))
 def c_is_staticdata(space, cppscope, datamember_index):
-    args = [_Arg(h=cppscope.handle), _Arg(l=datamember_index)]
+    args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
     return space.bool_w(call_capi(space, 'is_staticdata', args))
 
 # misc helpers ---------------------------------------------------------------
 def c_strtoll(space, svalue):
-    return space.r_longlong_w(call_capi(space, 'strtoll', [_Arg(s=svalue)]))
+    return space.r_longlong_w(call_capi(space, 'strtoll', [_ArgS(svalue)]))
 def c_strtoull(space, svalue):
-    return space.r_ulonglong_w(call_capi(space, 'strtoull', [_Arg(s=svalue)]))
+    return space.r_ulonglong_w(call_capi(space, 'strtoull', [_ArgS(svalue)]))
 def c_free(space, voidp):
-    call_capi(space, 'free', [_Arg(vp=voidp)])
+    call_capi(space, 'free', [_ArgP(voidp)])
 
 def charp2str_free(space, cdata):
     charp = rffi.cast(rffi.CCHARP, _cdata_to_ptr(space, cdata))
@@ -515,15 +570,60 @@
     c_free(space, rffi.cast(rffi.VOIDP, charp))
     return pystr
 
-def c_charp2stdstring(space, svalue):
-    return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)]))
+def c_charp2stdstring(space, svalue, sz):
+    return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring',
+        [_ArgS(svalue), _ArgH(rffi.cast(rffi.ULONG, sz))]))
+def c_stdstring2charp(space, cppstr):
+    sz = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+    try:
+        w_cstr = call_capi(space, 'stdstring2charp',
+            [_ArgH(cppstr), _ArgP(rffi.cast(rffi.VOIDP, sz))])
+        cstr_len = intmask(sz[0])
+    finally:
+        lltype.free(sz, flavor='raw')
+    return rffi.charpsize2str(_cdata_to_ccharp(space, w_cstr), cstr_len)
 def c_stdstring2stdstring(space, cppobject):
-    return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_Arg(h=cppobject)]))
+    return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgH(cppobject)]))
 
-# loadable-capi-specific pythonizations (none, as the capi isn't known until runtime)
+def c_stdvector_valuetype(space, pystr):
+    return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
+
+def c_stdvector_valuetype(space, pystr):
+    return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
+def c_stdvector_valuesize(space, pystr):
+    return _cdata_to_size_t(space, call_capi(space, 'stdvector_valuesize', [_ArgS(pystr)]))
+
+
+# TODO: factor these out ...
+# pythonizations
+def stdstring_c_str(space, w_self):
+    """Return a python string taking into account \0"""
+
+    from pypy.module.cppyy import interp_cppyy
+    cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
+    return space.wrap(c_stdstring2charp(space, cppstr._rawobject))
+
+# setup pythonizations for later use at run-time
+_pythonizations = {}
 def register_pythonizations(space):
     "NOT_RPYTHON"
-    pass
+
+    allfuncs = [
+
+        ### std::string
+        stdstring_c_str,
+
+    ]
+
+    for f in allfuncs:
+        _pythonizations[f.__name__] = space.wrap(interp2app(f))
+
+def _method_alias(space, w_pycppclass, m1, m2):
+    space.setattr(w_pycppclass, space.wrap(m1),
+                  space.getattr(w_pycppclass, space.wrap(m2)))
 
 def pythonize(space, name, w_pycppclass):
-    pass
+    if name == "string":
+        space.setattr(w_pycppclass, space.wrap("c_str"), _pythonizations["stdstring_c_str"])
+        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str")
+        _method_alias(space, w_pycppclass, "__str__",           "c_str")
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
deleted file mode 100644
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import py, os
-
-from rpython.rlib import libffi
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-
-__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary']
-
-pkgpath = py.path.local(__file__).dirpath().join(os.pardir)
-srcpath = pkgpath.join("src")
-incpath = pkgpath.join("include")
-
-import commands
-(config_stat, incdir) = commands.getstatusoutput("root-config --incdir")
-
-if os.environ.get("ROOTSYS"):
-    if config_stat != 0:     # presumably Reflex-only
-        rootincpath = [os.path.join(os.environ["ROOTSYS"], "include")]
-        rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
-    else:
-        rootincpath = [incdir]
-        rootlibpath = commands.getoutput("root-config --libdir").split()
-else:
-    if config_stat == 0:
-        rootincpath = [incdir]
-        rootlibpath = commands.getoutput("root-config --libdir").split()
-    else:
-        rootincpath = []
-        rootlibpath = []
-
-def identify():
-    return 'Reflex'
-
-ts_reflect = False
-ts_call    = 'auto'
-ts_memory  = 'auto'
-ts_helper  = 'auto'
-
-std_string_name = 'std::basic_string<char>'
-
-eci = ExternalCompilationInfo(
-    separate_module_files=[srcpath.join("reflexcwrapper.cxx")],
-    include_dirs=[incpath] + rootincpath,
-    includes=["reflexcwrapper.h"],
-    library_dirs=rootlibpath,
-    libraries=["Reflex"],
-    use_cpp_linker=True,
-)
-
-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
@@ -3,8 +3,8 @@
 from pypy.interpreter.error import OperationError, oefmt
 
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rlib.rarithmetic import r_singlefloat
-from rpython.rlib import jit_libffi, rfloat
+from rpython.rlib.rarithmetic import r_singlefloat, r_longfloat
+from rpython.rlib import rfloat
 
 from pypy.module._rawffi.interp_rawffi import letter2tp
 from pypy.module._rawffi.array import W_Array, W_ArrayInstance
@@ -81,11 +81,11 @@
 
 
 class TypeConverter(object):
-    _immutable_fields_ = ['libffitype', 'uses_local', 'name']
+    _immutable_fields_ = ['cffi_name', 'uses_local', 'name']
 
-    libffitype = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
+    cffi_name  = None
     uses_local = False
-    name = ""
+    name       = ""
 
     def __init__(self, space, extra):
         pass
@@ -103,6 +103,10 @@
         raise oefmt(space.w_TypeError,
                     "no converter available for '%s'", self.name)
 
+    def cffi_type(self, space):
+        from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible
+
     def convert_argument(self, space, w_obj, address, call_local):
         self._is_abstract(space)
 
@@ -143,9 +147,7 @@
 
 class ArrayTypeConverterMixin(object):
     _mixin_ = True
-    _immutable_fields_ = ['libffitype', 'size']
-
-    libffitype = jit_libffi.types.pointer
+    _immutable_fields_ = ['size']
 
     def __init__(self, space, array_size):
         if array_size <= 0:
@@ -153,6 +155,10 @@
         else:
             self.size = array_size
 
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
+
     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)
@@ -172,13 +178,15 @@
 
 class PtrTypeConverterMixin(object):
     _mixin_ = True
-    _immutable_fields_ = ['libffitype', 'size']
-
-    libffitype = jit_libffi.types.pointer
+    _immutable_fields_ = ['size']
 
     def __init__(self, space, array_size):
         self.size = sys.maxint
 
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
+
     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:
@@ -241,6 +249,10 @@
 
     uses_local = True
 
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
+
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         assert rffi.sizeof(self.c_type) <= 2*rffi.sizeof(rffi.VOIDP)  # see interp_cppyy.py
         obj = self._unwrap_object(space, w_obj)
@@ -255,6 +267,8 @@
     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(space)] = self.typecode
 
 class FloatTypeConverterMixin(NumericTypeConverterMixin):
     _mixin_ = True
@@ -267,13 +281,15 @@
 
 
 class VoidConverter(TypeConverter):
-    _immutable_fields_ = ['libffitype', 'name']
-
-    libffitype = jit_libffi.types.void
+    _immutable_fields_ = ['name']
 
     def __init__(self, space, name):
         self.name = name
 
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_void
+
     def convert_argument(self, space, w_obj, address, call_local):
         self._is_abstract(space)
 
@@ -282,6 +298,8 @@
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.LONGP, address)
         x[0] = self._unwrap_object(space, w_obj)
+        ba = rffi.cast(rffi.CCHARP, address)
+        ba[capi.c_function_arg_typeoffset(space)] = 'b'
 
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.LONGP, address)
@@ -305,6 +323,8 @@
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.CCHARP, address)
         x[0] = self._unwrap_object(space, w_obj)
+        ba = rffi.cast(rffi.CCHARP, address)
+        ba[capi.c_function_arg_typeoffset(space)] = 'b'
 
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         x = rffi.cast(self.c_ptrtype, address)
@@ -331,13 +351,15 @@
     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)
-        return space.wrap(float(rffiptr[0]))
+        return self._wrap_object(space, rffiptr[0])
 
 class ConstFloatRefConverter(FloatConverter):
-    _immutable_fields_ = ['libffitype', 'typecode']
+    _immutable_fields_ = ['typecode']
+    typecode = 'f'
 
-    libffitype = jit_libffi.types.pointer
-    typecode = 'F'
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
 
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
@@ -353,11 +375,22 @@
             self.default = rffi.cast(self.c_type, 0.)
 
 class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
-    _immutable_fields_ = ['libffitype', 'typecode']
+    _immutable_fields_ = ['typecode']
+    typecode = 'd'
 
-    libffitype = jit_libffi.types.pointer
-    typecode = 'D'
+class LongDoubleConverter(ffitypes.typeid(rffi.LONGDOUBLE), FloatTypeConverterMixin, TypeConverter):
+    _immutable_fields_ = ['default']
 
+    def __init__(self, space, default):
+        if default:
+            fval = float(rfloat.rstring_to_float(default))
+        else:
+            fval = float(0.)
+        self.default = r_longfloat(fval)
+
+class ConstLongDoubleRefConverter(ConstRefNumericTypeConverterMixin, LongDoubleConverter):
+    _immutable_fields_ = ['typecode']
+    typecode = 'g'
 
 class CStringConverter(TypeConverter):
     def convert_argument(self, space, w_obj, address, call_local):
@@ -377,10 +410,6 @@
 
 
 class VoidPtrConverter(TypeConverter):
-    _immutable_fields_ = ['libffitype']
-
-    libffitype = jit_libffi.types.pointer
-
     def _unwrap_object(self, space, w_obj):
         try:
             obj = get_rawbuffer(space, w_obj)
@@ -393,6 +422,10 @@
                 obj = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         return obj
 
+    def cffi_type(self, space):
+        state = space.fromcache(ffitypes.State)
+        return state.c_voidp
+
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.VOIDPP, address)
         x[0] = self._unwrap_object(space, w_obj)
@@ -422,9 +455,10 @@
             address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
 
 class VoidPtrPtrConverter(TypeConverter):
-    _immutable_fields_ = ['uses_local']
+    _immutable_fields_ = ['uses_local', 'typecode']
 
     uses_local = True
+    typecode = 'a'
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.VOIDPP, address)
@@ -435,7 +469,7 @@
         except TypeError:
             r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         x[0] = rffi.cast(rffi.VOIDP, call_local)
-        ba[capi.c_function_arg_typeoffset(space)] = 'a'
+        ba[capi.c_function_arg_typeoffset(space)] = self.typecode
 
     def finalize_call(self, space, w_obj, call_local):


More information about the pypy-commit mailing list