[pypy-commit] pypy win32-fixes3: merge default into branch

mattip noreply at buildbot.pypy.org
Fri Apr 26 13:49:37 CEST 2013


Author: mattip <matti.picus at gmail.com>
Branch: win32-fixes3
Changeset: r63637:3e90a9f82d4c
Date: 2013-04-26 14:47 +0300
http://bitbucket.org/pypy/pypy/changeset/3e90a9f82d4c/

Log:	merge default into branch

diff too long, truncating to 2000 out of 7762 lines

diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py
--- a/lib-python/2.7/test/test_descr.py
+++ b/lib-python/2.7/test/test_descr.py
@@ -3592,6 +3592,9 @@
         list.__init__(a, sequence=[0, 1, 2])
         self.assertEqual(a, [0, 1, 2])
 
+    @unittest.skipIf(test_support.check_impl_detail(pypy=True) and
+                     sys.platform == 'win32',
+                     "XXX: https://bugs.pypy.org/issue1461")
     def test_recursive_call(self):
         # Testing recursive __call__() by setting to instance of class...
         class A(object):
diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py
--- a/lib-python/2.7/test/test_fileio.py
+++ b/lib-python/2.7/test/test_fileio.py
@@ -318,7 +318,6 @@
         self.assertRaises(ValueError, _FileIO, -10)
         self.assertRaises(OSError, _FileIO, make_bad_fd())
         if sys.platform == 'win32':
-            raise unittest.SkipTest('Set _invalid_parameter_handler for low level io')
             import msvcrt
             self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd())
 
diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py
--- a/lib_pypy/msvcrt.py
+++ b/lib_pypy/msvcrt.py
@@ -8,25 +8,37 @@
 # PAC: 2010/08 added MS locking for Whoosh
 
 import ctypes
+import errno
 from ctypes_support import standard_c_lib as _c
 from ctypes_support import get_errno
-import errno
 
 try:
     open_osfhandle = _c._open_osfhandle
 except AttributeError: # we are not on windows
     raise ImportError
 
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
+try: from __pypy__ import builtinify, validate_fd
+except ImportError: builtinify = validate_fd = lambda f: f
 
 
 open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
 open_osfhandle.restype = ctypes.c_int
 
-get_osfhandle = _c._get_osfhandle
-get_osfhandle.argtypes = [ctypes.c_int]
-get_osfhandle.restype = ctypes.c_int
+_get_osfhandle = _c._get_osfhandle
+_get_osfhandle.argtypes = [ctypes.c_int]
+_get_osfhandle.restype = ctypes.c_int
+
+ at builtinify
+def get_osfhandle(fd):
+    """"get_osfhandle(fd) -> file handle
+
+    Return the file handle for the file descriptor fd. Raises IOError if
+    fd is not recognized."""
+    try:
+        validate_fd(fd)
+    except OSError as e:
+        raise IOError(*e.args)
+    return _get_osfhandle(fd)
 
 setmode = _c._setmode
 setmode.argtypes = [ctypes.c_int, ctypes.c_int]
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -35,7 +35,7 @@
      "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
      "binascii", "_multiprocessing", '_warnings',
      "_collections", "_multibytecodec", "micronumpy", "_ffi",
-     "_continuation", "_cffi_backend", "_csv"]
+     "_continuation", "_cffi_backend", "_csv", "cppyy"]
 ))
 
 translation_modules = default_modules.copy()
@@ -64,6 +64,8 @@
     del working_modules["termios"]
     del working_modules["_minimal_curses"]
 
+    del working_modules["cppyy"]  # not tested on win32
+
     # The _locale module is needed by site.py on Windows
     default_modules["_locale"] = None
 
@@ -75,7 +77,7 @@
     del working_modules["_minimal_curses"]
     del working_modules["termios"]
     del working_modules["_multiprocessing"]   # depends on rctime
-
+    del working_modules["cppyy"]  # depends on ctypes
 
 
 module_dependencies = {
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -2,94 +2,128 @@
 cppyy: C++ bindings for PyPy
 ============================
 
-The cppyy module provides C++ bindings for PyPy by using the reflection
-information extracted from C++ header files by means of the
-`Reflex package`_.
-For this to work, you have to both install Reflex and build PyPy from source,
-as the cppyy module is not enabled by default.
-Note that the development version of cppyy lives in the reflex-support
-branch.
-As indicated by this being a branch, support for Reflex is still
-experimental.
-However, it is functional enough to put it in the hands of those who want
-to give it a try.
-In the medium term, cppyy will move away from Reflex and instead use
-`cling`_ as its backend, which is based on `llvm`_.
-Although that will change the logistics on the generation of reflection
-information, it will not change the python-side interface.
+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.
 
-.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
+.. _`Reflex`: http://root.cern.ch/drupal/content/reflex
+.. _`CINT`: http://root.cern.ch/drupal/content/cint
 .. _`cling`: http://root.cern.ch/drupal/content/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
 ==========
 
-The cppyy module offers two unique features, which result in great
-performance as well as better functionality and cross-language integration
-than would otherwise be possible.
-First, cppyy is written in RPython and therefore open to optimizations by the
-JIT up until the actual point of call into C++.
-This means that there are no conversions necessary between a garbage collected
-and a reference counted environment, as is needed for the use of existing
-extension modules written or generated for CPython.
-It also means that if variables are already unboxed by the JIT, they can be
-passed through directly to C++.
-Second, Reflex (and cling far more so) adds dynamic features to C++, thus
-greatly reducing impedance mismatches between the two languages.
-In fact, Reflex is dynamic enough that you could write the runtime bindings
+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
 ============
 
-For now, the easiest way of getting the latest version of Reflex, is by
-installing the ROOT package.
-Besides getting the latest version of Reflex, another advantage is that with
-the full ROOT package, you can also use your Reflex-bound code on `CPython`_.
-`Download`_ a binary or install from `source`_.
-Some Linux and Mac systems may have ROOT provided in the list of scientific
-software of their packager.
-If, however, you prefer a standalone version of Reflex, the best is to get
-this `recent snapshot`_, and install like so::
+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 `backend documentation`_.
 
-    $ tar jxf reflex-2012-05-02.tar.bz2
-    $ cd reflex-2012-05-02
-    $ build/autogen
+.. _`backend documentation`: cppyy_backend.html
+
+A standalone version of Reflex that also provides the dynamically loadable
+backend is available for `download`_.
+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.
+
+.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.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-2013-04-23.tar.bz2
+    $ cd reflex-2013-04-23
+    $ ./build/autogen
     $ ./configure <usual set of options such as --prefix>
     $ make && make install
 
-Also, make sure you have a version of `gccxml`_ installed, which is most
-easily provided by the packager of your system.
-If you read up on gccxml, you'll 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`_.
+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``.
 
-.. _`Download`: http://root.cern.ch/drupal/content/downloading-root
-.. _`source`: http://root.cern.ch/drupal/content/installing-root-source
-.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2
-.. _`gccxml`: http://www.gccxml.org
+The following is optional, and is only to show how pypy-c can be build
+`from source`_, for example to get at the main development branch of cppyy.
+The `backend documentation`_ has more details on the backend-specific
+prerequisites.
 
-Next, get the `PyPy sources`_, optionally select the reflex-support branch,
-and build it.
-For the build to succeed, the ``$ROOTSYS`` environment variable must point to
-the location of your ROOT (or standalone Reflex) installation, or the
-``root-config`` utility must be accessible through ``PATH`` (e.g. by adding
-``$ROOTSYS/bin`` to ``PATH``).
-In case of the former, include files are expected under ``$ROOTSYS/include``
-and libraries under ``$ROOTSYS/lib``.
 Then run the translation to build ``pypy-c``::
 
     $ hg clone https://bitbucket.org/pypy/pypy
     $ cd pypy
     $ hg up reflex-support         # optional
-    $ cd pypy/goal
     
     # This example shows python, but using pypy-c is faster and uses less memory
-    $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy
+    $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
 
 This will build a ``pypy-c`` that includes the cppyy module, and through that,
 Reflex support.
@@ -98,12 +132,12 @@
 If not, you may want `to obtain a binary distribution`_ to speed up the
 translation step.
 
-.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview
+.. _`from source`: https://bitbucket.org/pypy/pypy/overview
 .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy
 
 
-Basic example
-=============
+Basic bindings example
+======================
 
 Now test with a trivial example whether all packages are properly installed
 and functional.
@@ -127,7 +161,7 @@
 code::
 
     $ genreflex MyClass.h
-    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex
+    $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex
 
 Now you're ready to use the bindings.
 Since the bindings are designed to look pythonistic, it should be
@@ -176,7 +210,7 @@
 For example::
 
     $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so
-    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex
+    $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex
 
 where the first option (``--rootmap``) specifies the output file name, and the
 second option (``--rootmap-lib``) the name of the reflection library where
@@ -277,7 +311,7 @@
 Now the reflection info can be generated and compiled::
 
     $ genreflex MyAdvanced.h --selection=MyAdvanced.xml
-    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex
+    $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex
 
 and subsequently be used from PyPy::
 
@@ -336,7 +370,7 @@
 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
+    $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex
 
 .. _`example code`: cppyy_example.html
 
@@ -595,6 +629,16 @@
   All template classes must already exist in the loaded reflection info, they
   do not work (yet) with the class loader.
 
+  For compatibility with other bindings generators, use of square brackets
+  instead of parenthesis to instantiate templates is supported as well.
+
+* **templated functions**: Automatically participate in overloading and are
+  used in the same way as other global functions.
+
+* **templated methods**: For now, require an explicit selection of the
+  template parameters.
+  This will be changed to allow them to participate in overloads as expected.
+
 * **typedefs**: Are simple python references to the actual classes to which
   they refer.
 
@@ -692,7 +736,7 @@
 Run the normal ``genreflex`` and compilation steps::
 
     $ genreflex MyTemplate.h --selection=MyTemplate.xml
-    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex
+    $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex
 
 Note: this is a dirty corner that clearly could do with some automation,
 even if the macro already helps.
@@ -727,18 +771,18 @@
 The fast lane
 =============
 
-The following is an experimental feature of cppyy, and that makes it doubly
-experimental, so caveat emptor.
+The following is an experimental feature of cppyy.
+It mostly works, but there are some known issues (e.g. with return-by-value).
+Soon it should be the default mode, however.
+
 With a slight modification of Reflex, it can provide function pointers for
 C++ methods, and hence allow PyPy to call those pointers directly, rather than
 calling C++ through a Reflex stub.
-This results in a rather significant speed-up.
-Mind you, the normal stub path is not exactly slow, so for now only use this
-out of curiosity or if you really need it.
 
-To install this patch of Reflex, locate the file genreflex-methptrgetter.patch
-in pypy/module/cppyy and apply it to the genreflex python scripts found in
-``$ROOTSYS/lib``::
+The standalone version of Reflex `provided`_ has been patched, but if you get
+Reflex from another source (most likely with a ROOT distribution), locate the
+file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to
+the genreflex python scripts found in ``$ROOTSYS/lib``::
 
     $ cd $ROOTSYS/lib
     $ patch -p2 < genreflex-methptrgetter.patch
@@ -749,8 +793,10 @@
 ``-Wno-pmf-conversions`` option to ``g++`` when compiling.
 The rest works the same way: the fast path will be used transparently (which
 also means that you can't actually find out whether it is in use, other than
-by running a micro-benchmark).
+by running a micro-benchmark or a JIT test).
 
+.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2
+.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch
 
 CPython
 =======
diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/cppyy_backend.rst
@@ -0,0 +1,53 @@
+==================
+Backends for cppyy
+==================
+
+The cppyy module needs a backend to provide the C++ reflection information on
+which the Python bindings are build.
+The backend is called through a C-API, which can be found in the PyPy sources
+in: `pypy/module/cppyy/include/capi.h`_.
+There are two kinds of API calls: querying about reflection information, which
+are used during the creation of Python-side constructs, and making the actual
+calls into C++.
+The objects passed around are all opaque: cppyy does not make any assumptions
+about them, other than that the opaque handles can be copied.
+Their definition, however, appears in two places: in the C code (in capi.h),
+and on the RPython side (in `capi_types.py`_), so if they are changed, they
+need to be changed on both sides.
+
+.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h
+.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py
+
+There are two places where selections in the RPython code affect the choice
+(and use) of the backend.
+The first is in `pypy/module/cppyy/capi/__init__.py`_::
+
+    # choose C-API access method:
+    from pypy.module.cppyy.capi.loadable_capi import *
+    #from pypy.module.cppyy.capi.builtin_capi import *
+
+The default is the loadable C-API.
+Comment it and uncomment the builtin C-API line, to use the builtin version.
+
+.. _`pypy/module/cppyy/capi/__init__.py`:  https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py
+
+Next, if the builtin C-API is chosen, the specific backend needs to be set as
+well (default is Reflex).
+This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_::
+
+    import reflex_capi as backend
+    #import cint_capi as backend
+
+After those choices have been made, built pypy-c as usual.
+
+.. _`pypy/module/cppyy/capi/builtin_capi.py`:  https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py
+
+When building pypy-c from source, keep the following in mind.
+If the loadable_capi is chosen, no further prerequisites are needed.
+However, for the build of the builtin_capi to succeed, the ``ROOTSYS``
+environment variable must point to the location of your ROOT (or standalone
+Reflex in the case of the Reflex backend) installation, or the ``root-config``
+utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin``
+to ``PATH``).
+In case of the former, include files are expected under ``$ROOTSYS/include``
+and libraries under ``$ROOTSYS/lib``.
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -57,10 +57,12 @@
 Inline the fast path of newarray in the assembler.
 Disabled on ARM until we fix issues.
 
+.. branch: reflex-support
+Allow dynamic loading of a (Reflex) backend that implements the C-API needed
+to provide reflection information
 
 .. branches we don't care about
 .. branch: autoreds
-.. branch: reflex-support
 .. branch: kill-faking
 .. branch: improved_ebnfparse_error
 .. branch: task-decorator
diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py
--- a/pypy/interpreter/astcompiler/consts.py
+++ b/pypy/interpreter/astcompiler/consts.py
@@ -15,8 +15,6 @@
 CO_FUTURE_WITH_STATEMENT = 0x8000
 CO_FUTURE_PRINT_FUNCTION = 0x10000
 CO_FUTURE_UNICODE_LITERALS = 0x20000
-CO_CONTAINSGLOBALS = 0x80000 # pypy-specific: need to check that it's not used
-                             # by any other flag
 
 PyCF_SOURCE_IS_UTF8 = 0x0100
 PyCF_DONT_IMPLY_DEDENT = 0x0200
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -12,7 +12,7 @@
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.interpreter.astcompiler.consts import (
     CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
-    CO_GENERATOR, CO_CONTAINSGLOBALS)
+    CO_GENERATOR)
 from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.objectmodel import compute_hash
@@ -88,8 +88,6 @@
         self._initialize()
 
     def _initialize(self):
-        self._init_flags()
-
         if self.co_cellvars:
             argcount = self.co_argcount
             assert argcount >= 0     # annotator hint
@@ -134,22 +132,6 @@
             '__pypy__' not in sys.builtin_module_names):
             raise Exception("CPython host codes should not be rendered")
 
-    def _init_flags(self):
-        co_code = self.co_code
-        next_instr = 0
-        while next_instr < len(co_code):
-            opcode = ord(co_code[next_instr])
-            next_instr += 1
-            if opcode >= HAVE_ARGUMENT:
-                next_instr += 2
-            while opcode == opcodedesc.EXTENDED_ARG.index:
-                opcode = ord(co_code[next_instr])
-                next_instr += 3
-            if opcode == opcodedesc.LOAD_GLOBAL.index:
-                self.co_flags |= CO_CONTAINSGLOBALS
-            elif opcode == opcodedesc.LOAD_NAME.index:
-                self.co_flags |= CO_CONTAINSGLOBALS
-
     co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace
 
     def signature(self):
diff --git a/pypy/interpreter/test/test_code.py b/pypy/interpreter/test/test_code.py
--- a/pypy/interpreter/test/test_code.py
+++ b/pypy/interpreter/test/test_code.py
@@ -9,7 +9,6 @@
             filename = filename[:-1]
 
         cls.w_file = cls.space.wrap(filename)
-        cls.w_CO_CONTAINSGLOBALS = cls.space.wrap(consts.CO_CONTAINSGLOBALS)
 
     def test_attributes(self):
         def f(): pass
@@ -183,27 +182,3 @@
         # CO_NESTED
         assert f(4).func_code.co_flags & 0x10
         assert f.func_code.co_flags & 0x10 == 0
-        # check for CO_CONTAINSGLOBALS
-        assert not f.func_code.co_flags & self.CO_CONTAINSGLOBALS
-
-
-        exec """if 1:
-        r = range
-        def f():
-            return [l for l in r(100)]
-        def g():
-            return [l for l in [1, 2, 3, 4]]
-"""
-
-        # check for CO_CONTAINSGLOBALS
-        assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS
-        assert not g.func_code.co_flags & self.CO_CONTAINSGLOBALS
-
-        exec """if 1:
-        b = 2
-        def f(x):
-            exec "a = 1";
-            return a + b + x
-"""
-        # check for CO_CONTAINSGLOBALS
-        assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -1,16 +1,16 @@
-from pypy.module._io.interp_iobase import W_IOBase
-from pypy.interpreter.typedef import (
-    TypeDef, GetSetProperty, interp_attrproperty_w, interp_attrproperty,
-    generic_new_descr)
-from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
+import sys
+
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError
-from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_uint
+from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import (
+    GetSetProperty, TypeDef, generic_new_descr, interp_attrproperty,
+    interp_attrproperty_w)
+from pypy.module._codecs import interp_codecs
+from pypy.module._io.interp_iobase import W_IOBase, convert_size
+from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rstring import UnicodeBuilder
-from pypy.module._codecs import interp_codecs
-from pypy.module._io.interp_iobase import convert_size
-import sys
 
 
 STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
@@ -270,6 +270,27 @@
     errors = GetSetProperty(W_TextIOBase.errors_get_w),
 )
 
+
+def _determine_encoding(space, encoding):
+    if encoding is not None:
+        return space.wrap(encoding)
+
+    try:
+        w_locale = space.call_method(space.builtin, '__import__',
+                                     space.wrap('locale'))
+        w_encoding = space.call_method(w_locale, 'getpreferredencoding')
+    except OperationError as e:
+        # getpreferredencoding() may also raise ImportError
+        if not e.match(space, space.w_ImportError):
+            raise
+        return space.wrap('ascii')
+    else:
+        if space.isinstance_w(w_encoding, space.w_str):
+            return w_encoding
+
+    raise OperationError(space.w_IOError, space.wrap(
+            "could not determine default encoding"))
+
 class PositionCookie(object):
     def __init__(self, bigint):
         self.start_pos = bigint.ulonglongmask()
@@ -337,32 +358,8 @@
     def descr_init(self, space, w_buffer, encoding=None,
                    w_errors=None, w_newline=None, line_buffering=0):
         self.state = STATE_ZERO
-
         self.w_buffer = w_buffer
-
-        # Set encoding
-        self.w_encoding = None
-        if encoding is None:
-            try:
-                w_locale = space.call_method(space.builtin, '__import__',
-                                             space.wrap("locale"))
-                self.w_encoding = space.call_method(w_locale,
-                                                    "getpreferredencoding")
-            except OperationError, e:
-                # getpreferredencoding() may also raise ImportError
-                if not e.match(space, space.w_ImportError):
-                    raise
-                self.w_encoding = space.wrap("ascii")
-            else:
-                if not space.isinstance_w(self.w_encoding, space.w_str):
-                    self.w_encoding = None
-        if self.w_encoding:
-            pass
-        elif encoding is not None:
-            self.w_encoding = space.wrap(encoding)
-        else:
-            raise OperationError(space.w_IOError, space.wrap(
-                "could not determine default encoding"))
+        self.w_encoding = _determine_encoding(space, encoding)
 
         if space.is_none(w_errors):
             w_errors = space.wrap("strict")
diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py
--- a/pypy/module/_minimal_curses/__init__.py
+++ b/pypy/module/_minimal_curses/__init__.py
@@ -1,6 +1,6 @@
 try:
     import _curses
-except ImportError:
+except Exception:   # probably ImportError or cffi's VerificationError
     try:
         # when running on top of pypy before it had _curses, settle for minimal
         # we prefer _curses so any constants added make it into _minimal_curses
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
@@ -10,15 +10,17 @@
         '_resolve_name'          : 'interp_cppyy.resolve_name',
         '_scope_byname'          : 'interp_cppyy.scope_byname',
         '_template_byname'       : 'interp_cppyy.template_byname',
+        '_std_string_name'       : 'interp_cppyy.std_string_name',
         '_set_class_generator'   : 'interp_cppyy.set_class_generator',
         '_register_class'        : 'interp_cppyy.register_class',
+        '_is_static'             : 'interp_cppyy.is_static',
         'CPPInstance'            : 'interp_cppyy.W_CPPInstance',
         'addressof'              : 'interp_cppyy.addressof',
         'bind_object'            : 'interp_cppyy.bind_object',
     }
 
     appleveldefs = {
-        'gbl'                    : 'pythonify.gbl',
+        '_init_pythonify'        : 'pythonify._init_pythonify',
         'load_reflection_info'   : 'pythonify.load_reflection_info',
         'add_pythonization'      : 'pythonify.add_pythonization',
     }
@@ -31,3 +33,9 @@
         # code generation is not, so give it a chance to run now
         from pypy.module.cppyy import capi
         capi.register_pythonizations(space)
+
+    def startup(self, space):
+        from pypy.module.cppyy import capi
+        capi.verify_backend(space)      # may raise ImportError
+
+        space.call_method(space.wrap(self), '_init_pythonify')
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
@@ -1,37 +1,19 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rlib import jit
 
-import reflex_capi as backend
-#import cint_capi as backend
+# There are two possible ways of accessing the backend through the reflection
+# C-API: built it into pypy-c, or load it dynamically. The latter is preferred
+# (and is the default) for use with Reflex. B/c of some builtin pythonizations,
+# the former is recommended (for now) with CINT.
 
-identify  = backend.identify
-pythonize = backend.pythonize
-register_pythonizations = backend.register_pythonizations
+# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still
+# the selection of the desired backend (default is Reflex).
 
-ts_reflect = backend.ts_reflect
-ts_call    = backend.ts_call
-ts_memory  = backend.ts_memory
-ts_helper  = backend.ts_helper
+# choose C-API access method:
+from pypy.module.cppyy.capi.loadable_capi import *
+#from pypy.module.cppyy.capi.builtin_capi import *
 
-_C_OPAQUE_PTR = rffi.LONG
-_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO
-
-C_SCOPE = _C_OPAQUE_PTR
-C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL)
-
-C_TYPE = C_SCOPE
-C_NULL_TYPE = C_NULL_SCOPE
-
-C_OBJECT = _C_OPAQUE_PTR
-C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL)
-
-C_METHOD = _C_OPAQUE_PTR
-C_INDEX = rffi.LONG
-C_INDEX_ARRAY = rffi.LONGP
-WLAVC_INDEX = rffi.LONG
-
-C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
-C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
+from pypy.module.cppyy.capi.capi_types import C_OBJECT,\
+    C_NULL_TYPE, C_NULL_OBJECT
 
 def direct_ptradd(ptr, offset):
     offset = rffi.cast(rffi.SIZE_T, offset)
@@ -42,457 +24,3 @@
 
 def exchange_address(ptr, cif_descr, index):
     return rffi.ptradd(ptr, cif_descr.exchange_args[index])
-
-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,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_resolve_name(name):
-    return charp2str_free(_c_resolve_name(name))
-c_get_scope_opaque = rffi.llexternal(
-    "cppyy_get_scope",
-    [rffi.CCHARP], C_SCOPE,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-c_get_template = rffi.llexternal(
-    "cppyy_get_template",
-    [rffi.CCHARP], C_TYPE,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-_c_actual_class = rffi.llexternal(
-    "cppyy_actual_class",
-    [C_TYPE, C_OBJECT], C_TYPE,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_actual_class(cppclass, cppobj):
-    return _c_actual_class(cppclass.handle, cppobj)
-
-# memory management ----------------------------------------------------------
-_c_allocate = rffi.llexternal(
-    "cppyy_allocate",
-    [C_TYPE], C_OBJECT,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci)
-def c_allocate(cppclass):
-    return _c_allocate(cppclass.handle)
-_c_deallocate = rffi.llexternal(
-    "cppyy_deallocate",
-    [C_TYPE, C_OBJECT], lltype.Void,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci)
-def c_deallocate(cppclass, cppobject):
-    _c_deallocate(cppclass.handle, cppobject)
-_c_destruct = rffi.llexternal(
-    "cppyy_destruct",
-    [C_TYPE, C_OBJECT], lltype.Void,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-def c_destruct(cppclass, cppobject):
-    _c_destruct(cppclass.handle, cppobject)
-
-# method/function dispatching ------------------------------------------------
-c_call_v = rffi.llexternal(
-    "cppyy_call_v",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_b = rffi.llexternal(
-    "cppyy_call_b",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_c = rffi.llexternal(
-    "cppyy_call_c",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_h = rffi.llexternal(
-    "cppyy_call_h",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_i = rffi.llexternal(
-    "cppyy_call_i",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_l = rffi.llexternal(
-    "cppyy_call_l",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_ll = rffi.llexternal(
-    "cppyy_call_ll",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_f = rffi.llexternal(
-    "cppyy_call_f",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_d = rffi.llexternal(
-    "cppyy_call_d",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-
-c_call_r = rffi.llexternal(
-    "cppyy_call_r",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-c_call_s = rffi.llexternal(
-    "cppyy_call_s",
-    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP,
-    threadsafe=ts_call,
-    compilation_info=backend.eci)
-
-c_constructor = rffi.llexternal(
-    "cppyy_constructor",
-    [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, 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,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci,
-    elidable_function=True)
-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(
-    "cppyy_allocate_function_args",
-    [rffi.SIZE_T], rffi.VOIDP,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci)
-c_deallocate_function_args = rffi.llexternal(
-    "cppyy_deallocate_function_args",
-    [rffi.VOIDP], lltype.Void,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci)
-c_function_arg_sizeof = rffi.llexternal(
-    "cppyy_function_arg_sizeof",
-    [], rffi.SIZE_T,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci,
-    elidable_function=True)
-c_function_arg_typeoffset = rffi.llexternal(
-    "cppyy_function_arg_typeoffset",
-    [], rffi.SIZE_T,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci,
-    elidable_function=True)
-
-# scope reflection information -----------------------------------------------
-c_is_namespace = rffi.llexternal(
-    "cppyy_is_namespace",
-    [C_SCOPE], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-c_is_enum = rffi.llexternal(
-    "cppyy_is_enum",
-    [rffi.CCHARP], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-
-# type/class reflection information ------------------------------------------
-_c_final_name = rffi.llexternal(
-    "cppyy_final_name",
-    [C_TYPE], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_final_name(cpptype):
-    return charp2str_free(_c_final_name(cpptype))
-_c_scoped_final_name = rffi.llexternal(
-    "cppyy_scoped_final_name",
-    [C_TYPE], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_scoped_final_name(cpptype):
-    return charp2str_free(_c_scoped_final_name(cpptype))
-c_has_complex_hierarchy = rffi.llexternal(
-    "cppyy_has_complex_hierarchy",
-    [C_TYPE], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-_c_num_bases = rffi.llexternal(
-    "cppyy_num_bases",
-    [C_TYPE], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_num_bases(cppclass):
-    return _c_num_bases(cppclass.handle)
-_c_base_name = rffi.llexternal(
-    "cppyy_base_name",
-    [C_TYPE, rffi.INT], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    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,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci,
-    elidable_function=True)
- at jit.elidable_promote()
-def c_is_subtype(derived, base):
-    if derived == base:
-        return 1
-    return _c_is_subtype(derived.handle, base.handle)
-
-_c_base_offset = rffi.llexternal(
-    "cppyy_base_offset",
-    [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci,
-    elidable_function=True)
- at jit.elidable_promote()
-def c_base_offset(derived, base, address, direction):
-    if derived == base:
-        return 0
-    return _c_base_offset(derived.handle, base.handle, address, direction)
-
-# method/function reflection information -------------------------------------
-_c_num_methods = rffi.llexternal(
-    "cppyy_num_methods",
-    [C_SCOPE], rffi.INT,
-    threadsafe=ts_reflect,
-    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_indices_from_name = rffi.llexternal(
-    "cppyy_method_indices_from_name",
-    [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_method_indices_from_name(cppscope, name):
-    indices = _c_method_indices_from_name(cppscope.handle, name)
-    if not indices:
-        return []
-    py_indices = []
-    i = 0
-    index = indices[i]
-    while index != -1:
-        i += 1
-        py_indices.append(index)
-        index = indices[i]
-    c_free(rffi.cast(rffi.VOIDP, indices))   # c_free defined below
-    return py_indices
-
-_c_method_name = rffi.llexternal(
-    "cppyy_method_name",
-    [C_SCOPE, C_INDEX], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX, rffi.INT], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX, rffi.INT], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], C_METHOD,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-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, C_INDEX], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_is_constructor(cppclass, index):
-    return _c_is_constructor(cppclass.handle, index)
-_c_is_staticmethod = rffi.llexternal(
-    "cppyy_is_staticmethod",
-    [C_TYPE, C_INDEX], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_is_staticmethod(cppclass, index):
-    return _c_is_staticmethod(cppclass.handle, index)
-
-# data member reflection information -----------------------------------------
-_c_num_datamembers = rffi.llexternal(
-    "cppyy_num_datamembers",
-    [C_SCOPE], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_num_datamembers(cppscope):
-    return _c_num_datamembers(cppscope.handle)
-_c_datamember_name = rffi.llexternal(
-    "cppyy_datamember_name",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_datamember_name(cppscope, datamember_index):
-    return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index))
-_c_datamember_type = rffi.llexternal(
-    "cppyy_datamember_type",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_datamember_type(cppscope, datamember_index):
-    return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index))
-_c_datamember_offset = rffi.llexternal(
-    "cppyy_datamember_offset",
-    [C_SCOPE, rffi.INT], rffi.SIZE_T,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_datamember_offset(cppscope, datamember_index):
-    return _c_datamember_offset(cppscope.handle, datamember_index)
-
-_c_datamember_index = rffi.llexternal(
-    "cppyy_datamember_index",
-    [C_SCOPE, rffi.CCHARP], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_datamember_index(cppscope, name):
-    return _c_datamember_index(cppscope.handle, name)
-
-# data member properties -----------------------------------------------------
-_c_is_publicdata = rffi.llexternal(
-    "cppyy_is_publicdata",
-    [C_SCOPE, rffi.INT], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_is_publicdata(cppscope, datamember_index):
-    return _c_is_publicdata(cppscope.handle, datamember_index)
-_c_is_staticdata = rffi.llexternal(
-    "cppyy_is_staticdata",
-    [C_SCOPE, rffi.INT], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_is_staticdata(cppscope, datamember_index):
-    return _c_is_staticdata(cppscope.handle, datamember_index)
-
-# misc helpers ---------------------------------------------------------------
-c_strtoll = rffi.llexternal(
-    "cppyy_strtoll",
-    [rffi.CCHARP], rffi.LONGLONG,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
-c_strtoull = rffi.llexternal(
-    "cppyy_strtoull",
-    [rffi.CCHARP], rffi.ULONGLONG,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
-c_free = rffi.llexternal(
-    "cppyy_free",
-    [rffi.VOIDP], lltype.Void,
-    threadsafe=ts_memory,
-    compilation_info=backend.eci)
-
-def charp2str_free(charp):
-    string = rffi.charp2str(charp)
-    voidp = rffi.cast(rffi.VOIDP, charp)
-    c_free(voidp)
-    return string
-
-c_charp2stdstring = rffi.llexternal(
-    "cppyy_charp2stdstring",
-    [rffi.CCHARP], C_OBJECT,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
-c_stdstring2stdstring = rffi.llexternal(
-    "cppyy_stdstring2stdstring",
-    [C_OBJECT], C_OBJECT,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
-c_assign2stdstring = rffi.llexternal(
-    "cppyy_assign2stdstring",
-    [C_OBJECT, rffi.CCHARP], lltype.Void,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
-c_free_stdstring = rffi.llexternal(
-    "cppyy_free_stdstring",
-    [C_OBJECT], lltype.Void,
-    threadsafe=ts_helper,
-    compilation_info=backend.eci)
diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/capi/builtin_capi.py
@@ -0,0 +1,561 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib import jit
+
+import reflex_capi as backend
+#import cint_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
+
+identify  = backend.identify
+pythonize = backend.pythonize
+register_pythonizations = backend.register_pythonizations
+std_string_name = backend.std_string_name
+
+ts_reflect = backend.ts_reflect
+ts_call    = backend.ts_call
+ts_memory  = backend.ts_memory
+ts_helper  = backend.ts_helper
+
+def verify_backend(space):
+    return True                    # by definition
+
+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(space, 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(space, cppscope, iscope):
+    return charp2str_free(space, _c_scope_name(cppscope.handle, iscope))
+
+_c_resolve_name = rffi.llexternal(
+    "cppyy_resolve_name",
+    [rffi.CCHARP], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_resolve_name(space, name):
+    return charp2str_free(space, _c_resolve_name(name))
+_c_get_scope_opaque = rffi.llexternal(
+    "cppyy_get_scope",
+    [rffi.CCHARP], C_SCOPE,
+    threadsafe=ts_reflect,
+    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,
+    threadsafe=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,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_actual_class(space, cppclass, cppobj):
+    return _c_actual_class(cppclass.handle, cppobj)
+
+# memory management ----------------------------------------------------------
+_c_allocate = rffi.llexternal(
+    "cppyy_allocate",
+    [C_TYPE], C_OBJECT,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci)
+def c_allocate(space, cppclass):
+    return _c_allocate(cppclass.handle)
+_c_deallocate = rffi.llexternal(
+    "cppyy_deallocate",
+    [C_TYPE, C_OBJECT], lltype.Void,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci)
+def c_deallocate(space, cppclass, cppobject):
+    _c_deallocate(cppclass.handle, cppobject)
+_c_destruct = rffi.llexternal(
+    "cppyy_destruct",
+    [C_TYPE, C_OBJECT], lltype.Void,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_destruct(space, cppclass, cppobject):
+    _c_destruct(cppclass.handle, cppobject)
+
+# method/function dispatching ------------------------------------------------
+_c_call_v = rffi.llexternal(
+    "cppyy_call_v",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_v(space, cppmethod, cppobject, nargs, args):
+    _c_call_v(cppmethod, cppobject, nargs, args)
+_c_call_b = rffi.llexternal(
+    "cppyy_call_b",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_b(space, cppmethod, cppobject, nargs, args):
+    return _c_call_b(cppmethod, cppobject, nargs, args)
+_c_call_c = rffi.llexternal(
+    "cppyy_call_c",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_c(space, cppmethod, cppobject, nargs, args):
+    return _c_call_c(cppmethod, cppobject, nargs, args)
+_c_call_h = rffi.llexternal(
+    "cppyy_call_h",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_h(space, cppmethod, cppobject, nargs, args):
+    return _c_call_h(cppmethod, cppobject, nargs, args)
+_c_call_i = rffi.llexternal(
+    "cppyy_call_i",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_i(space, cppmethod, cppobject, nargs, args):
+    return _c_call_i(cppmethod, cppobject, nargs, args)
+_c_call_l = rffi.llexternal(
+    "cppyy_call_l",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_l(space, cppmethod, cppobject, nargs, args):
+    return _c_call_l(cppmethod, cppobject, nargs, args)
+_c_call_ll = rffi.llexternal(
+    "cppyy_call_ll",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_ll(space, cppmethod, cppobject, nargs, args):
+    return _c_call_ll(cppmethod, cppobject, nargs, args)
+_c_call_f = rffi.llexternal(
+    "cppyy_call_f",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_f(space, cppmethod, cppobject, nargs, args):
+    return _c_call_f(cppmethod, cppobject, nargs, args)
+_c_call_d = rffi.llexternal(
+    "cppyy_call_d",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_d(space, cppmethod, cppobject, nargs, args):
+    return _c_call_d(cppmethod, cppobject, nargs, args)
+
+_c_call_r = rffi.llexternal(
+    "cppyy_call_r",
+    [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_r(space, cppmethod, cppobject, nargs, args):
+    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,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_call_s(space, cppmethod, cppobject, nargs, args):
+    return _c_call_s(cppmethod, cppobject, nargs, args)
+
+_c_constructor = rffi.llexternal(
+    "cppyy_constructor",
+    [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT,
+    threadsafe=ts_call,
+    compilation_info=backend.eci)
+def c_constructor(space, cppmethod, cppobject, nargs, args):
+    return _c_constructor(cppmethod, cppobject, nargs, args)
+_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(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,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci,
+    elidable_function=True)
+def c_get_methptr_getter(space, cppscope, index):
+    return _c_get_methptr_getter(cppscope.handle, index)
+
+# handling of function argument buffer ---------------------------------------
+_c_allocate_function_args = rffi.llexternal(
+    "cppyy_allocate_function_args",
+    [rffi.SIZE_T], rffi.VOIDP,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci)
+def c_allocate_function_args(space, size):
+    return _c_allocate_function_args(size)
+_c_deallocate_function_args = rffi.llexternal(
+    "cppyy_deallocate_function_args",
+    [rffi.VOIDP], lltype.Void,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci)
+def c_deallocate_function_args(space, args):
+    _c_deallocate_function_args(args)
+_c_function_arg_sizeof = rffi.llexternal(
+    "cppyy_function_arg_sizeof",
+    [], rffi.SIZE_T,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci,
+    elidable_function=True)
+def c_function_arg_sizeof(space):
+    return _c_function_arg_sizeof()
+_c_function_arg_typeoffset = rffi.llexternal(
+    "cppyy_function_arg_typeoffset",
+    [], rffi.SIZE_T,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci,
+    elidable_function=True)
+def c_function_arg_typeoffset(space):
+    return _c_function_arg_typeoffset()
+
+# scope reflection information -----------------------------------------------
+_c_is_namespace = rffi.llexternal(
+    "cppyy_is_namespace",
+    [C_SCOPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_namespace(space, scope):
+    return _c_is_namespace(scope)
+_c_is_enum = rffi.llexternal(
+    "cppyy_is_enum",
+    [rffi.CCHARP], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_enum(space, name):
+    return _c_is_enum(name)
+
+# type/class reflection information ------------------------------------------
+_c_final_name = rffi.llexternal(
+    "cppyy_final_name",
+    [C_TYPE], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_final_name(space, cpptype):
+    return charp2str_free(space, _c_final_name(cpptype))
+_c_scoped_final_name = rffi.llexternal(
+    "cppyy_scoped_final_name",
+    [C_TYPE], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_scoped_final_name(space, cpptype):
+    return charp2str_free(space, _c_scoped_final_name(cpptype))
+_c_has_complex_hierarchy = rffi.llexternal(
+    "cppyy_has_complex_hierarchy",
+    [C_TYPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_has_complex_hierarchy(space, cpptype):
+    return _c_has_complex_hierarchy(cpptype)
+_c_num_bases = rffi.llexternal(
+    "cppyy_num_bases",
+    [C_TYPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_num_bases(space, cppclass):
+    return _c_num_bases(cppclass.handle)
+_c_base_name = rffi.llexternal(
+    "cppyy_base_name",
+    [C_TYPE, rffi.INT], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_base_name(space, cppclass, base_index):
+    return charp2str_free(space, _c_base_name(cppclass.handle, base_index))
+_c_is_subtype = rffi.llexternal(
+    "cppyy_is_subtype",
+    [C_TYPE, C_TYPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci,
+    elidable_function=True)
+ at jit.elidable_promote('2')
+def c_is_subtype(space, derived, base):
+    if derived == base:
+        return 1
+    return _c_is_subtype(derived.handle, base.handle)
+
+_c_base_offset = rffi.llexternal(
+    "cppyy_base_offset",
+    [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci,
+    elidable_function=True)
+ at jit.elidable_promote('1,2,4')
+def c_base_offset(space, derived, base, address, direction):
+    if derived == base:
+        return 0
+    return _c_base_offset(derived.handle, base.handle, address, direction)
+def c_base_offset1(space, derived_h, base, address, direction):
+    return _c_base_offset(derived_h, base.handle, address, direction)
+
+# method/function reflection information -------------------------------------
+_c_num_methods = rffi.llexternal(
+    "cppyy_num_methods",
+    [C_SCOPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_num_methods(space, 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(space, cppscope, imethod):
+    return _c_method_index_at(cppscope.handle, imethod)
+_c_method_indices_from_name = rffi.llexternal(
+    "cppyy_method_indices_from_name",
+    [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_indices_from_name(space, cppscope, name):
+    indices = _c_method_indices_from_name(cppscope.handle, name)
+    if not indices:
+        return []
+    py_indices = []
+    i = 0
+    index = indices[i]
+    while index != -1:
+        i += 1
+        py_indices.append(index)
+        index = indices[i]
+    c_free(rffi.cast(rffi.VOIDP, indices))   # c_free defined below
+    return py_indices
+
+_c_method_name = rffi.llexternal(
+    "cppyy_method_name",
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_name(space, cppscope, index):
+    return charp2str_free(space, _c_method_name(cppscope.handle, index))
+_c_method_result_type = rffi.llexternal(
+    "cppyy_method_result_type",
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_result_type(space, cppscope, index):
+    return charp2str_free(space, _c_method_result_type(cppscope.handle, index))
+_c_method_num_args = rffi.llexternal(
+    "cppyy_method_num_args",
+    [C_SCOPE, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_num_args(space, cppscope, index):
+    return _c_method_num_args(cppscope.handle, index)
+_c_method_req_args = rffi.llexternal(
+    "cppyy_method_req_args",
+    [C_SCOPE, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_req_args(space, cppscope, index):
+    return _c_method_req_args(cppscope.handle, index)
+_c_method_arg_type = rffi.llexternal(
+    "cppyy_method_arg_type",
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_arg_type(space, cppscope, index, arg_index):
+    return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index))
+_c_method_arg_default = rffi.llexternal(
+    "cppyy_method_arg_default",
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_arg_default(space, cppscope, index, arg_index):
+    return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index))
+_c_method_signature = rffi.llexternal(
+    "cppyy_method_signature",
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_signature(space, cppscope, index):
+    return charp2str_free(space, _c_method_signature(cppscope.handle, index))
+
+_c_method_is_template = rffi.llexternal(
+    "cppyy_method_is_template",
+    [C_SCOPE, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_is_template(space, cppscope, index):
+    return _c_method_is_template(cppscope.handle, index)
+_c_method_num_template_args = rffi.llexternal(
+    "cppyy_method_num_template_args",
+    [C_SCOPE, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+_c_method_template_arg_name = rffi.llexternal(
+    "cppyy_method_template_arg_name",
+    [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_template_args(space, cppscope, index):
+    nargs = _c_method_num_template_args(cppscope.handle, index)
+    args = [c_resolve_name(space,
+        charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg)))
+        for iarg in range(nargs)]
+    return args
+
+_c_get_method = rffi.llexternal(
+    "cppyy_get_method",
+    [C_SCOPE, C_INDEX], C_METHOD,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_get_method(space, 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(space, 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, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_constructor(space, cppclass, index):
+    return _c_is_constructor(cppclass.handle, index)
+_c_is_staticmethod = rffi.llexternal(
+    "cppyy_is_staticmethod",
+    [C_TYPE, C_INDEX], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_staticmethod(space, cppclass, index):
+    return _c_is_staticmethod(cppclass.handle, index)
+
+# data member reflection information -----------------------------------------
+_c_num_datamembers = rffi.llexternal(
+    "cppyy_num_datamembers",
+    [C_SCOPE], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_num_datamembers(space, cppscope):
+    return _c_num_datamembers(cppscope.handle)
+_c_datamember_name = rffi.llexternal(
+    "cppyy_datamember_name",
+    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_datamember_name(space, cppscope, datamember_index):
+    return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index))
+_c_datamember_type = rffi.llexternal(
+    "cppyy_datamember_type",
+    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_datamember_type(space, cppscope, datamember_index):
+    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,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_datamember_offset(space, cppscope, datamember_index):
+    return _c_datamember_offset(cppscope.handle, datamember_index)
+
+_c_datamember_index = rffi.llexternal(
+    "cppyy_datamember_index",
+    [C_SCOPE, rffi.CCHARP], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_datamember_index(space, cppscope, name):
+    return _c_datamember_index(cppscope.handle, name)
+
+# data member properties -----------------------------------------------------
+_c_is_publicdata = rffi.llexternal(
+    "cppyy_is_publicdata",
+    [C_SCOPE, rffi.INT], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_publicdata(space, cppscope, datamember_index):
+    return _c_is_publicdata(cppscope.handle, datamember_index)
+_c_is_staticdata = rffi.llexternal(
+    "cppyy_is_staticdata",
+    [C_SCOPE, rffi.INT], rffi.INT,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_is_staticdata(space, cppscope, datamember_index):
+    return _c_is_staticdata(cppscope.handle, datamember_index)
+
+# misc helpers ---------------------------------------------------------------
+_c_strtoll = rffi.llexternal(
+    "cppyy_strtoll",
+    [rffi.CCHARP], rffi.LONGLONG,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_strtoll(space, svalue):
+    return _c_strtoll(svalue)
+_c_strtoull = rffi.llexternal(
+    "cppyy_strtoull",
+    [rffi.CCHARP], rffi.ULONGLONG,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_strtoull(space, svalue):
+    return _c_strtoull(svalue)
+c_free = rffi.llexternal(
+    "cppyy_free",
+    [rffi.VOIDP], lltype.Void,
+    threadsafe=ts_memory,
+    compilation_info=backend.eci)
+
+def charp2str_free(space, charp):
+    string = rffi.charp2str(charp)
+    voidp = rffi.cast(rffi.VOIDP, charp)
+    c_free(voidp)
+    return string
+
+_c_charp2stdstring = rffi.llexternal(
+    "cppyy_charp2stdstring",
+    [rffi.CCHARP], C_OBJECT,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_charp2stdstring(space, svalue):
+    charp = rffi.str2charp(svalue)
+    result = _c_charp2stdstring(charp)
+    rffi.free_charp(charp)
+    return result
+_c_stdstring2stdstring = rffi.llexternal(
+    "cppyy_stdstring2stdstring",
+    [C_OBJECT], C_OBJECT,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_stdstring2stdstring(space, cppobject):
+    return _c_stdstring2stdstring(cppobject)
+_c_assign2stdstring = rffi.llexternal(
+    "cppyy_assign2stdstring",
+    [C_OBJECT, rffi.CCHARP], lltype.Void,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_assign2stdstring(space, cppobject, svalue):
+    charp = rffi.str2charp(svalue)
+    _c_assign2stdstring(cppobject, charp)
+    rffi.free_charp(charp)
+_c_free_stdstring = rffi.llexternal(
+    "cppyy_free_stdstring",
+    [C_OBJECT], lltype.Void,
+    threadsafe=ts_helper,
+    compilation_info=backend.eci)
+def c_free_stdstring(space, cppobject):
+    _c_free_stdstring(cppobject)
diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/capi/capi_types.py
@@ -0,0 +1,22 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+
+# shared ll definitions
+_C_OPAQUE_PTR = rffi.LONG
+_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO
+
+C_SCOPE = _C_OPAQUE_PTR
+C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL)
+
+C_TYPE = C_SCOPE
+C_NULL_TYPE = C_NULL_SCOPE
+
+C_OBJECT = _C_OPAQUE_PTR
+C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL)
+
+C_METHOD = _C_OPAQUE_PTR
+C_INDEX = rffi.LONG
+C_INDEX_ARRAY = rffi.LONGP
+WLAVC_INDEX = rffi.LONG
+
+C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
+C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
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
@@ -9,10 +9,8 @@
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rlib import libffi, rdynload
 
-from pypy.module.itertools import interp_itertools
 
-
-__all__ = ['identify', 'eci', 'c_load_dictionary']
+__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary']
 
 pkgpath = py.path.local(__file__).dirpath().join(os.pardir)
 srcpath = pkgpath.join("src")
@@ -36,8 +34,10 @@
 
 ts_reflect = False
 ts_call    = False
-ts_memory  = 'auto'
-ts_helper  = 'auto'
+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
@@ -120,7 +120,7 @@
             classname = space.str_w(args_w[1])
             addr_idx  = 2
             w_address = args_w[addr_idx]
-        except OperationError:
+        except (OperationError, TypeError):
             addr_idx  = 1
             w_address = args_w[addr_idx]
 
@@ -138,14 +138,14 @@
         # 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)
+        w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class)
         return w_branch
-    except (OperationError, TypeError, IndexError), e:
+    except (OperationError, TypeError, IndexError):
         pass
 
     # return control back to the original, unpythonized overload
-    return tree_class.get_overload("Branch").call(w_self, args_w)
+    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")
@@ -155,6 +155,12 @@
     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,
+    threadsafe=False,
+    compilation_info=eci)
+
 @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
@@ -163,28 +169,75 @@
     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
-    space = tree.space            # holds the class cache in State
     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.int_w(space.call_method(w_self, "GetReadEntry"))
+    if entry == -1:
+        entry = 0
+
+    # setup cache structure
     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
+    if space.is_true(w_klassname):
+        # some instance
+        klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname))
+        w_obj = klass.construct()
+        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.buffer_w(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.tree = tree.get_cppthis(tree.cppclass)
+        self.vtree = rffi.cast(rffi.VOIDP, 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"))
 
@@ -198,8 +251,8 @@
         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
+        c_ttree_GetEntry(self.vtree, self.current)
+        self.current += 1 
         return self.w_tree
 
 W_TTreeIter.typedef = TypeDef(
diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -0,0 +1,519 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+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.error import OperationError
+
+from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
+
+from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\


More information about the pypy-commit mailing list