[pypy-commit] pypy py3k: merge default

pjenvey noreply at buildbot.pypy.org
Thu Apr 24 01:42:55 CEST 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r70902:23776e232207
Date: 2014-04-23 16:41 -0700
http://bitbucket.org/pypy/pypy/changeset/23776e232207/

Log:	merge default

diff too long, truncating to 2000 out of 9793 lines

diff --git a/lib-python/2.7/ctypes/util.py b/lib-python/2.7/ctypes/util.py
--- a/lib-python/2.7/ctypes/util.py
+++ b/lib-python/2.7/ctypes/util.py
@@ -86,9 +86,10 @@
 
 elif os.name == "posix":
     # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
-    import re, tempfile, errno
+    import re, errno
 
     def _findLib_gcc(name):
+        import tempfile
         expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
         fdout, ccout = tempfile.mkstemp()
         os.close(fdout)
diff --git a/lib-python/2.7/test/test_argparse.py b/lib-python/2.7/test/test_argparse.py
--- a/lib-python/2.7/test/test_argparse.py
+++ b/lib-python/2.7/test/test_argparse.py
@@ -51,7 +51,7 @@
         for root, dirs, files in os.walk(self.temp_dir, topdown=False):
             for name in files:
                 os.chmod(os.path.join(self.temp_dir, name), stat.S_IWRITE)
-        shutil.rmtree(self.temp_dir, True)        
+        shutil.rmtree(self.temp_dir, True)
 
     def create_readonly_file(self, filename):
         file_path = os.path.join(self.temp_dir, filename)
diff --git a/lib-python/2.7/test/test_httpservers.py b/lib-python/2.7/test/test_httpservers.py
--- a/lib-python/2.7/test/test_httpservers.py
+++ b/lib-python/2.7/test/test_httpservers.py
@@ -335,7 +335,7 @@
             response = self.request(self.tempdir_name + '/')
             self.check_status_and_reason(response, 404)
             os.chmod(self.tempdir, 0755)
-        f.close()    
+        f.close()
 
     def test_head(self):
         response = self.request(
diff --git a/lib_pypy/_pypy_testcapi.py b/lib_pypy/_pypy_testcapi.py
--- a/lib_pypy/_pypy_testcapi.py
+++ b/lib_pypy/_pypy_testcapi.py
@@ -1,6 +1,7 @@
 import os, sys, imp
 import tempfile, binascii
 
+
 def get_hashed_dir(cfile):
     with open(cfile,'r') as fid:
         content = fid.read()
@@ -15,7 +16,7 @@
     output_dir = tempfile.gettempdir() + os.path.sep + 'tmp_%s%s' %(k1, k2)
     if not os.path.exists(output_dir):
         os.mkdir(output_dir)
-    return output_dir 
+    return output_dir
 
 
 def _get_c_extension_suffix():
diff --git a/lib_pypy/ctypes_support.py b/lib_pypy/ctypes_support.py
--- a/lib_pypy/ctypes_support.py
+++ b/lib_pypy/ctypes_support.py
@@ -1,4 +1,3 @@
-
 """ This file provides some support for things like standard_c_lib and
 errno access, as portable as possible
 """
@@ -22,7 +21,7 @@
     standard_c_lib._errno.argtypes = None
     def _where_is_errno():
         return standard_c_lib._errno()
-    
+
 elif sys.platform in ('linux2', 'freebsd6'):
     standard_c_lib.__errno_location.restype = ctypes.POINTER(ctypes.c_int)
     standard_c_lib.__errno_location.argtypes = None
@@ -42,5 +41,3 @@
 def set_errno(value):
     errno_p = _where_is_errno()
     errno_p.contents.value = value
-
-
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -15,21 +15,21 @@
   Alex Gaynor
   Michael Hudson
   David Schneider
+  Matti Picus
+  Brian Kearns
+  Philip Jenvey
   Holger Krekel
   Christian Tismer
-  Matti Picus
   Hakan Ardo
   Benjamin Peterson
-  Philip Jenvey
+  Manuel Jacob
   Anders Chrigstrom
-  Brian Kearns
-  Manuel Jacob
   Eric van Riet Paap
   Wim Lavrijsen
+  Ronan Lamy
   Richard Emslie
   Alexander Schremmer
   Dan Villiom Podlaski Christiansen
-  Ronan Lamy
   Lukas Diekmann
   Sven Hager
   Anders Lehmann
@@ -38,23 +38,23 @@
   Camillo Bruni
   Laura Creighton
   Toon Verwaest
+  Remi Meier
   Leonardo Santagada
   Seo Sanghyeon
+  Romain Guillebert
   Justin Peel
   Ronny Pfannschmidt
   David Edelsohn
   Anders Hammarquist
   Jakub Gustak
-  Romain Guillebert
   Guido Wesdorp
   Lawrence Oluyede
-  Remi Meier
   Bartosz Skowron
   Daniel Roberts
   Niko Matsakis
   Adrien Di Mascio
+  Alexander Hesse
   Ludovic Aubry
-  Alexander Hesse
   Jacob Hallen
   Jason Creighton
   Alex Martelli
@@ -71,6 +71,7 @@
   Bruno Gola
   Jean-Paul Calderone
   Timo Paulssen
+  Squeaky
   Alexandre Fayolle
   Simon Burton
   Marius Gedminas
@@ -87,6 +88,7 @@
   Paweł Piotr Przeradowski
   Paul deGrandis
   Ilya Osadchiy
+  Tobias Oberstein
   Adrian Kuhn
   Boris Feigin
   Stefano Rivera
@@ -95,13 +97,17 @@
   Georg Brandl
   Bert Freudenberg
   Stian Andreassen
+  Laurence Tratt
   Wanja Saatkamp
   Gerald Klix
   Mike Blume
   Oscar Nierstrasz
   Stefan H. Muller
-  Laurence Tratt
+  Jeremy Thurgood
+  Gregor Wegberg
   Rami Chowdhury
+  Tobias Pape
+  Edd Barrett
   David Malcolm
   Eugene Oden
   Henry Mason
@@ -110,9 +116,7 @@
   David Ripton
   Dusty Phillips
   Lukas Renggli
-  Edd Barrett
   Guenter Jantzen
-  Tobias Oberstein
   Ned Batchelder
   Amit Regmi
   Ben Young
@@ -123,7 +127,6 @@
   Nicholas Riley
   Jason Chu
   Igor Trindade Oliveira
-  Jeremy Thurgood
   Rocco Moretti
   Gintautas Miliauskas
   Michael Twomey
@@ -134,7 +137,6 @@
   Olivier Dormond
   Jared Grubb
   Karl Bartel
-  Tobias Pape
   Brian Dorsey
   Victor Stinner
   Andrews Medina
@@ -146,9 +148,9 @@
   Aaron Iles
   Michael Cheng
   Justas Sadzevicius
+  Mikael Schönenberg
   Gasper Zejn
   Neil Shepperd
-  Mikael Schönenberg
   Elmo Mäntynen
   Jonathan David Riehl
   Stanislaw Halik
@@ -161,7 +163,9 @@
   Alexander Sedov
   Corbin Simpson
   Christopher Pope
+  wenzhuman
   Christian Tismer 
+  Marc Abramowitz
   Dan Stromberg
   Stefano Parmesan
   Alexis Daboville
@@ -170,6 +174,7 @@
   Karl Ramm
   Pieter Zieschang
   Gabriel
+  Lukas Vacek
   Andrew Dalke
   Sylvain Thenault
   Nathan Taylor
@@ -180,6 +185,7 @@
   Travis Francis Athougies
   Kristjan Valur Jonsson
   Neil Blakey-Milner
+  anatoly techtonik
   Lutz Paelike
   Lucio Torre
   Lars Wassermann
@@ -200,7 +206,6 @@
   Bobby Impollonia
   timo at eistee.fritz.box
   Andrew Thompson
-  Yusei Tahara
   Ben Darnell
   Roberto De Ioris
   Juan Francisco Cantero Hurtado
@@ -212,28 +217,35 @@
   Anders Sigfridsson
   Yasir Suhail
   Floris Bruynooghe
+  Laurens Van Houtven
   Akira Li
   Gustavo Niemeyer
   Stephan Busemann
   Rafał Gałczyński
+  Yusei Tahara
   Christian Muirhead
   James Lan
   shoma hosaka
-  Daniel Neuhäuser
+  Daniel Neuh?user
+  Matthew Miller
   Buck Golemon
   Konrad Delong
   Dinu Gherman
   Chris Lambacher
   coolbutuseless at gmail.com
+  Rodrigo Araújo
   w31rd0
   Jim Baker
-  Rodrigo Araújo
+  James Robert
   Armin Ronacher
   Brett Cannon
   yrttyr
+  aliceinwire
+  OlivierBlanvillain
   Zooko Wilcox-O Hearn
   Tomer Chachamu
   Christopher Groskopf
+  jiaaro
   opassembler.py
   Antony Lee
   Jim Hunziker
@@ -241,6 +253,7 @@
   Even Wiik Thomassen
   jbs
   soareschen
+  Kurt Griffiths
   Mike Bayer
   Flavio Percoco
   Kristoffer Kleine
diff --git a/pypy/doc/release-2.3.0.rst b/pypy/doc/release-2.3.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.3.0.rst
@@ -0,0 +1,88 @@
+=======================================
+PyPy 2.3 - XXXX TODO
+=======================================
+
+We're pleased to announce PyPy 2.3, which targets version 2.7.6 of the Python
+language. This release updates the stdlib from 2.7.3, jumping directly to 2.7.6.
+
+This release also contains several bugfixes and performance improvements. 
+
+You can download the PyPy 2.3 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project. We showed quite a bit of progress on all three projects (see below)
+and we're slowly running out of funds.
+Please consider donating more so we can finish those projects!  The three
+projects are:
+
+* Py3k (supporting Python 3.x): the release PyPy3 2.2 is imminent.
+
+* STM (software transactional memory): a preview will be released very soon,
+  as soon as we fix a few bugs
+
+* NumPy: the work done is included in the PyPy 2.2 release. More details below.
+
+.. _`Raspberry Pi Foundation`: http://www.raspberrypi.org
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.2 and cpython 2.7.2`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows
+32, or ARM (ARMv6 or ARMv7, with VFPv3).
+
+Work on the native Windows 64 is still stalling, we would welcome a volunteer
+to handle that.
+
+.. _`pypy 2.2 and cpython 2.7.2`: http://speed.pypy.org
+
+Highlights
+==========
+
+* Our Garbage Collector is now "incremental".  It should avoid almost
+  all pauses due to a major collection taking place.  Previously, it
+  would pause the program (rarely) to walk all live objects, which
+  could take arbitrarily long if your process is using a whole lot of
+  RAM.  Now the same work is done in steps.  This should make PyPy
+  more responsive, e.g. in games.  There are still other pauses, from
+  the GC and the JIT, but they should be on the order of 5
+  milliseconds each.
+
+* The JIT counters for hot code were never reset, which meant that a
+  process running for long enough would eventually JIT-compile more
+  and more rarely executed code.  Not only is it useless to compile
+  such code, but as more compiled code means more memory used, this
+  gives the impression of a memory leak.  This has been tentatively
+  fixed by decreasing the counters from time to time.
+
+* NumPy has been split: now PyPy only contains the core module, called
+  ``_numpypy``.  The ``numpy`` module itself has been moved to
+  ``https://bitbucket.org/pypy/numpy`` and ``numpypy`` disappeared.
+  You need to install NumPy separately with a virtualenv:
+  ``pip install git+https://bitbucket.org/pypy/numpy.git``;
+  or directly:
+  ``git clone https://bitbucket.org/pypy/numpy.git``;
+  ``cd numpy``; ``pypy setup.py install``.
+
+* non-inlined calls have less overhead
+
+* Things that use ``sys.set_trace`` are now JITted (like coverage)
+
+* JSON decoding is now very fast (JSON encoding was already very fast)
+
+* various buffer copying methods experience speedups (like list-of-ints to
+  ``int[]`` buffer from cffi)
+
+* We finally wrote (hopefully) all the missing ``os.xxx()`` functions,
+  including ``os.startfile()`` on Windows and a handful of rare ones
+  on Posix.
+
+* numpy has a rudimentary C API that cooperates with ``cpyext``
+
+Cheers,
+Armin Rigo and Maciej Fijalkowski
diff --git a/pypy/doc/whatsnew-2.3.0.rst b/pypy/doc/whatsnew-2.3.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-2.3.0.rst
@@ -0,0 +1,154 @@
+=======================
+What's new in PyPy 2.2+
+=======================
+
+.. this is a revision shortly after release-2.2.x
+.. startrev: 4cd1bc8b3111
+
+.. branch: release-2.2.x
+
+.. branch: numpy-newbyteorder
+Clean up numpy types, add newbyteorder functionality
+
+.. branch: windows-packaging
+Package tk/tcl runtime with win32
+
+.. branch: armhf-singlefloat
+JIT support for singlefloats on ARM using the hardfloat ABI
+
+.. branch: voidtype_strformat
+Better support for record numpy arrays
+
+.. branch: osx-eci-frameworks-makefile
+OSX: Ensure frameworks end up in Makefile when specified in External compilation info
+
+.. branch: less-stringly-ops
+Use subclasses of SpaceOperation instead of SpaceOperator objects.
+Random cleanups in flowspace and annotator.
+
+.. branch: ndarray-buffer
+adds support for the buffer= argument to the ndarray ctor
+
+.. branch: better_ftime_detect2
+On OpenBSD do not pull in libcompat.a as it is about to be removed.
+And more generally, if you have gettimeofday(2) you will not need ftime(3).
+
+.. branch: timeb_h
+Remove dependency upon <sys/timeb.h> on OpenBSD. This will be disappearing
+along with libcompat.a.
+
+.. branch: OlivierBlanvillain/fix-3-broken-links-on-pypy-published-pap-1386250839215
+Fix 3 broken links on PyPy published papers in docs.
+
+.. branch: jit-ordereddict
+
+.. branch: refactor-str-types
+Remove multimethods on str/unicode/bytearray and make the implementations share code.
+
+.. branch: remove-del-from-generatoriterator
+Speed up generators that don't yield inside try or wait blocks by skipping
+unnecessary cleanup.
+
+.. branch: annotator
+Remove FlowObjSpace.
+Improve cohesion between rpython.flowspace and rpython.annotator.
+
+.. branch: detect-immutable-fields
+mapdicts keep track of whether or not an attribute is every assigned to
+multiple times. If it's only assigned once then an elidable lookup is used when
+possible.
+
+.. branch: precompiled-headers
+Create a Makefile using precompiled headers for MSVC platforms.
+The downside is a messy nmake-compatible Makefile. Since gcc shows minimal
+speedup, it was not implemented.
+
+.. branch: camelot
+With a properly configured 256-color terminal (TERM=...-256color), the
+Mandelbrot set shown during translation now uses a range of 50 colours.
+Essential!
+
+.. branch: NonConstant
+Simplify implementation of NonConstant.
+
+.. branch: array-propagate-len
+Kill some guards and operations in JIT traces by adding integer bounds
+propagation for getfield_(raw|gc) and getarrayitem_(raw|gc).
+
+.. branch: optimize-int-and
+Optimize away INT_AND with constant mask of 1s that fully cover the bitrange
+of other operand.
+
+.. branch: bounds-int-add-or
+Propagate appropriate bounds through INT_(OR|XOR|AND) operations if the
+operands are positive to kill some guards
+
+.. branch: remove-intlong-smm
+kills int/long/smalllong/bool multimethods
+
+.. branch: numpy-refactor
+Cleanup micronumpy module
+
+.. branch: int_w-refactor
+In a lot of places CPython allows objects with __int__ and __float__ instead of actual ints and floats, while until now pypy disallowed them. We fix it by making space.{int_w,float_w,etc.} accepting those objects by default, and disallowing conversions only when explicitly needed.
+
+.. branch: test-58c3d8552833
+Fix for getarrayitem_gc_pure optimization
+
+.. branch: simple-range-strategy
+Implements SimpleRangeListStrategy for case range(n) where n is a positive number.
+Makes some traces nicer by getting rid of multiplication for calculating loop counter
+and propagates that n > 0 further to get rid of guards.
+
+.. branch: popen-pclose
+Provide an exit status for popen'ed RFiles via pclose
+
+.. branch: stdlib-2.7.6
+Update stdlib to v2.7.6
+
+.. branch: virtual-raw-store-load
+Support for virtualizing raw_store/raw_load operations
+
+.. branch: refactor-buffer-api
+Separate the interp-level buffer API from the buffer type exposed to
+app-level.  The `Buffer` class is now used by `W_MemoryView` and
+`W_Buffer`, which is not present in Python 3.  Previously `W_Buffer` was
+an alias to `Buffer`, which was wrappable itself.
+
+.. branch: improve-consecutive-dict-lookups
+Improve the situation when dict lookups of the same key are performed in a chain
+
+.. branch: add_PyErr_SetFromErrnoWithFilenameObject_try_2
+.. branch: test_SetFromErrnoWithFilename_NULL
+.. branch: test_SetFromErrnoWithFilename__tweaks
+
+.. branch: refactor_PyErr_SetFromErrnoWithFilename
+Add support for PyErr_SetFromErrnoWithFilenameObject to cpyext
+
+.. branch: win32-fixes4
+fix more tests for win32
+
+.. branch: latest-improve-doc
+Fix broken links in documentation
+
+.. branch: ast-issue1673
+fix ast classes __dict__ are always empty problem and fix the ast deepcopy issue when 
+there is missing field
+
+.. branch: issue1514
+Fix issues with reimporting builtin modules
+
+.. branch: numpypy-nditer
+Implement the core of nditer, without many of the fancy flags (external_loop, buffered)
+
+.. branch: numpy-speed
+Separate iterator from its state so jit can optimize better
+
+.. branch: numpy-searchsorted
+Implement searchsorted without sorter kwarg
+
+.. branch: openbsd-lib-prefix
+add 'lib' prefix to link libraries on OpenBSD
+
+.. branch: small-unroll-improvements
+Improve optimization of small allocation-heavy loops in the JIT
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
@@ -1,145 +1,11 @@
 =======================
-What's new in PyPy 2.2+
+What's new in PyPy 2.3+
 =======================
 
-.. this is a revision shortly after release-2.2.x
-.. startrev: 4cd1bc8b3111
+.. this is a revision shortly after release-2.3.x
+.. startrev: ba569fe1efdb
 
-.. branch: release-2.2.x
+.. branch: small-unroll-improvements
+Improve optimiziation of small allocation-heavy loops in the JIT
 
-.. branch: numpy-newbyteorder
-Clean up numpy types, add newbyteorder functionality
-
-.. branch: windows-packaging
-Package tk/tcl runtime with win32
-
-.. branch: armhf-singlefloat
-JIT support for singlefloats on ARM using the hardfloat ABI
-
-.. branch: voidtype_strformat
-Better support for record numpy arrays
-
-.. branch: osx-eci-frameworks-makefile
-OSX: Ensure frameworks end up in Makefile when specified in External compilation info
-
-.. branch: less-stringly-ops
-Use subclasses of SpaceOperation instead of SpaceOperator objects.
-Random cleanups in flowspace and annotator.
-
-.. branch: ndarray-buffer
-adds support for the buffer= argument to the ndarray ctor
-
-.. branch: better_ftime_detect2
-On OpenBSD do not pull in libcompat.a as it is about to be removed.
-And more generally, if you have gettimeofday(2) you will not need ftime(3).
-
-.. branch: timeb_h
-Remove dependency upon <sys/timeb.h> on OpenBSD. This will be disappearing
-along with libcompat.a.
-
-.. branch: OlivierBlanvillain/fix-3-broken-links-on-pypy-published-pap-1386250839215
-Fix 3 broken links on PyPy published papers in docs.
-
-.. branch: jit-ordereddict
-
-.. branch: refactor-str-types
-Remove multimethods on str/unicode/bytearray and make the implementations share code.
-
-.. branch: remove-del-from-generatoriterator
-Speed up generators that don't yield inside try or wait blocks by skipping
-unnecessary cleanup.
-
-.. branch: annotator
-Remove FlowObjSpace.
-Improve cohesion between rpython.flowspace and rpython.annotator.
-
-.. branch: detect-immutable-fields
-mapdicts keep track of whether or not an attribute is every assigned to
-multiple times. If it's only assigned once then an elidable lookup is used when
-possible.
-
-.. branch: precompiled-headers
-Create a Makefile using precompiled headers for MSVC platforms.
-The downside is a messy nmake-compatible Makefile. Since gcc shows minimal
-speedup, it was not implemented.
-
-.. branch: camelot
-With a properly configured 256-color terminal (TERM=...-256color), the
-Mandelbrot set shown during translation now uses a range of 50 colours.
-Essential!
-
-.. branch: NonConstant
-Simplify implementation of NonConstant.
-
-.. branch: array-propagate-len
-Kill some guards and operations in JIT traces by adding integer bounds
-propagation for getfield_(raw|gc) and getarrayitem_(raw|gc).
-
-.. branch: optimize-int-and
-Optimize away INT_AND with constant mask of 1s that fully cover the bitrange
-of other operand.
-
-.. branch: bounds-int-add-or
-Propagate appropriate bounds through INT_(OR|XOR|AND) operations if the
-operands are positive to kill some guards
-
-.. branch: remove-intlong-smm
-kills int/long/smalllong/bool multimethods
-
-.. branch: numpy-refactor
-Cleanup micronumpy module
-
-.. branch: int_w-refactor
-In a lot of places CPython allows objects with __int__ and __float__ instead of actual ints and floats, while until now pypy disallowed them. We fix it by making space.{int_w,float_w,etc.} accepting those objects by default, and disallowing conversions only when explicitly needed.
-
-.. branch: test-58c3d8552833
-Fix for getarrayitem_gc_pure optimization
-
-.. branch: simple-range-strategy
-Implements SimpleRangeListStrategy for case range(n) where n is a positive number.
-Makes some traces nicer by getting rid of multiplication for calculating loop counter
-and propagates that n > 0 further to get rid of guards.
-
-.. branch: popen-pclose
-Provide an exit status for popen'ed RFiles via pclose
-
-.. branch: stdlib-2.7.6
-Update stdlib to v2.7.6
-
-.. branch: virtual-raw-store-load
-Support for virtualizing raw_store/raw_load operations
-
-.. branch: refactor-buffer-api
-Separate the interp-level buffer API from the buffer type exposed to
-app-level.  The `Buffer` class is now used by `W_MemoryView` and
-`W_Buffer`, which is not present in Python 3.  Previously `W_Buffer` was
-an alias to `Buffer`, which was wrappable itself.
-
-.. branch: improve-consecutive-dict-lookups
-Improve the situation when dict lookups of the same key are performed in a chain
-
-.. branch: add_PyErr_SetFromErrnoWithFilenameObject_try_2
-.. branch: test_SetFromErrnoWithFilename_NULL
-.. branch: test_SetFromErrnoWithFilename__tweaks
-
-.. branch: refactor_PyErr_SetFromErrnoWithFilename
-Add support for PyErr_SetFromErrnoWithFilenameObject to cpyext
-
-.. branch: win32-fixes4
-fix more tests for win32
-
-.. branch: latest-improve-doc
-Fix broken links in documentation
-
-.. branch: ast-issue1673
-fix ast classes __dict__ are always empty problem and fix the ast deepcopy issue when 
-there is missing field
-
-.. branch: issue1514
-Fix issues with reimporting builtin modules
-
-.. branch: numpypy-nditer
-Implement the core of nditer, without many of the fancy flags (external_loop, buffered)
-
-.. branch: numpy-speed
-Separate iterator from its state so jit can optimize better
+.. branch: reflex-support
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -89,8 +89,23 @@
 http://hboehm.info/gc/gc_source/gc-7.1.tar.gz
 
 Versions 7.0 and 7.1 are known to work; the 6.x series won't work with
-pypy. Unpack this folder in the base directory.  Then open a command
-prompt::
+pypy. Unpack this folder in the base directory. 
+The default GC_abort(...) function in misc.c will try to open a MessageBox.
+You may want to disable this with the following patch::
+
+    --- a/misc.c    Sun Apr 20 14:08:27 2014 +0300
+    +++ b/misc.c    Sun Apr 20 14:08:37 2014 +0300
+    @@ -1058,7 +1058,7 @@
+     #ifndef PCR
+      void GC_abort(const char *msg)
+       {
+       -#   if defined(MSWIN32)
+       +#   if 0 && defined(MSWIN32)
+              (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
+               #   else
+                      GC_err_printf("%s\n", msg);
+    
+Then open a command prompt::
 
     cd gc-7.1
     nmake -f NT_THREADS_MAKEFILE
diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py
--- a/pypy/module/_sre/interp_sre.py
+++ b/pypy/module/_sre/interp_sre.py
@@ -34,8 +34,9 @@
 
 def slice_w(space, ctx, start, end, w_default):
     if 0 <= start <= end:
-        if isinstance(ctx, rsre_core.StrMatchContext):
-            return space.wrapbytes(ctx._string[start:end])
+        if isinstance(ctx, rsre_core.BufMatchContext):
+            return space.wrapbytes(ctx._buffer.getslice(start, end, 1,
+                                                        end-start))
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr[start:end])
         else:
@@ -97,7 +98,7 @@
                              space.wrap("cannot copy this pattern object"))
 
     def make_ctx(self, w_string, pos=0, endpos=sys.maxint):
-        """Make a StrMatchContext or a UnicodeMatchContext for searching
+        """Make a BufMatchContext or a UnicodeMatchContext for searching
         in the given w_string object."""
         space = self.space
         if pos < 0:
@@ -117,16 +118,18 @@
             return rsre_core.UnicodeMatchContext(self.code, unicodestr,
                                                  pos, endpos, self.flags)
         else:
-            str = space.bufferstr_w(w_string)
+            buf = space.buffer_w(w_string)
             if (not space.is_none(self.w_pattern) and
                 space.isinstance_w(self.w_pattern, space.w_unicode)):
                 raise OperationError(space.w_TypeError, space.wrap(
                         "can't use a bytes pattern on a string-like object"))
-            if pos > len(str):
-                pos = len(str)
-            if endpos > len(str):
-                endpos = len(str)
-            return rsre_core.StrMatchContext(self.code, str,
+            size = buf.getlength()
+            assert size >= 0
+            if pos > size:
+                pos = size
+            if endpos > size:
+                endpos = size
+            return rsre_core.BufMatchContext(self.code, buf,
                                              pos, endpos, self.flags)
 
     def getmatch(self, ctx, found):
@@ -488,8 +491,8 @@
 
     def fget_string(self, space):
         ctx = self.ctx
-        if isinstance(ctx, rsre_core.StrMatchContext):
-            return space.wrapbytes(ctx._string)
+        if isinstance(ctx, rsre_core.BufMatchContext):
+            return space.wrapbytes(ctx._buffer.as_str())
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr)
         else:
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
@@ -12,8 +12,10 @@
         '_template_byname'       : 'interp_cppyy.template_byname',
         '_std_string_name'       : 'interp_cppyy.std_string_name',
         '_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',
         'CPPInstance'            : 'interp_cppyy.W_CPPInstance',
         'addressof'              : 'interp_cppyy.addressof',
         'bind_object'            : 'interp_cppyy.bind_object',
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
@@ -190,7 +190,8 @@
     [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR,
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True)
+    elidable_function=True,
+    random_effects_on_gcobjs=False)
 def c_get_methptr_getter(space, cppscope, index):
     return _c_get_methptr_getter(cppscope.handle, index)
 
@@ -214,7 +215,8 @@
     [], rffi.SIZE_T,
     releasegil=ts_memory,
     compilation_info=backend.eci,
-    elidable_function=True)
+    elidable_function=True,
+    random_effects_on_gcobjs=False)
 def c_function_arg_sizeof(space):
     return _c_function_arg_sizeof()
 _c_function_arg_typeoffset = rffi.llexternal(
@@ -222,7 +224,8 @@
     [], rffi.SIZE_T,
     releasegil=ts_memory,
     compilation_info=backend.eci,
-    elidable_function=True)
+    elidable_function=True,
+    random_effects_on_gcobjs=False)
 def c_function_arg_typeoffset(space):
     return _c_function_arg_typeoffset()
 
@@ -283,7 +286,8 @@
     [C_TYPE, C_TYPE], rffi.INT,
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True)
+    elidable_function=True,
+    random_effects_on_gcobjs=False)
 @jit.elidable_promote('2')
 def c_is_subtype(space, derived, base):
     if derived == base:
@@ -295,7 +299,8 @@
     [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T,
     releasegil=ts_reflect,
     compilation_info=backend.eci,
-    elidable_function=True)
+    elidable_function=True,
+    random_effects_on_gcobjs=False)
 @jit.elidable_promote('1,2,4')
 def c_base_offset(space, derived, base, address, direction):
     if derived == base:
@@ -543,19 +548,3 @@
     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,
-    releasegil=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,
-    releasegil=ts_helper,
-    compilation_info=backend.eci)
-def c_free_stdstring(space, cppobject):
-    _c_free_stdstring(cppobject)
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
@@ -6,8 +6,11 @@
 from pypy.interpreter.baseobjspace import W_Root
 
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem import rffi
+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']
@@ -19,21 +22,21 @@
 if os.environ.get("ROOTSYS"):
     import commands
     (stat, incdir) = commands.getstatusoutput("root-config --incdir")
-    if stat != 0:        # presumably Reflex-only
-        rootincpath = [os.path.join(os.environ["ROOTSYS"], "include")]
+    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]
+        rootincpath = [incdir, py.path.local(udir)]
         rootlibpath = commands.getoutput("root-config --libdir").split()
 else:
-    rootincpath = []
+    rootincpath = [py.path.local(udir)]
     rootlibpath = []
 
 def identify():
     return 'CINT'
 
-ts_reflect = False
-ts_call    = False
+ts_reflect = True
+ts_call    = True
 ts_memory  = False
 ts_helper  = False
 
@@ -47,13 +50,15 @@
     _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=["Core", "Cint"],
+    libraries=["Hist", "Core", "Cint"],
     use_cpp_linker=True,
 )
 
@@ -71,6 +76,23 @@
 
 
 # CINT-specific pythonizations ===============================================
+_c_charp2TString = rffi.llexternal(
+    "cppyy_charp2TString",
+    [rffi.CCHARP], C_OBJECT,
+    releasegil=ts_helper,
+    compilation_info=eci)
+def c_charp2TString(space, svalue):
+    charp = rffi.str2charp(svalue)
+    result = _c_charp2TString(charp)
+    rffi.free_charp(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
@@ -80,10 +102,85 @@
         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:
+        # Note: argcount is +1 for the class (== w_self)
+        if argc < 5 or 6 < argc:
+            raise TypeError("wrong number of arguments")
+
+        # second argument must be a name
+        funcname = space.str_w(args_w[1])
+
+        # last (optional) argument is number of parameters
+        npar = 0
+        if argc == 6: npar = space.int_w(args_w[5])
+
+        # third argument must be a callable python object
+        w_callable = args_w[2]
+        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[1]), funcaddr,
+                      space.float_w(args_w[3]), space.float_w(args_w[4]), npar)
+ 
+        from pypy.module.cppyy import interp_cppyy
+        w_instance = interp_cppyy.wrap_cppobject(space, newinst, tf1_class,
+                                      do_cast=False, python_owns=True, fresh=True)
+
+        # tie all the life times to the TF1 instance
+        space.setattr(w_instance, space.wrap('_callback'), w_callback)
+
+        return w_instance
+    except (OperationError, TypeError, IndexError), 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], rffi.LONG,
+    [rffi.VOIDP, rffi.CCHARP, rffi.CCHARP, rffi.VOIDP, rffi.INT, rffi.INT], C_OBJECT,
     releasegil=False,
     compilation_info=eci)
 
@@ -202,6 +299,8 @@
         # 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)
@@ -274,6 +373,9 @@
 
     allfuncs = [
 
+        ### TF1
+        tf1_tf1,
+
         ### TTree
         ttree_Branch, ttree_iter, ttree_getattr,
     ]
@@ -288,7 +390,14 @@
 # callback coming in when app-level bound classes have been created
 def pythonize(space, name, w_pycppclass):
 
-    if name == "TFile":
+    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("__new__"), _pythonizations["tf1_tf1"])
+
+    elif name == "TFile":
         _method_alias(space, w_pycppclass, "__getattr__", "Get")
 
     elif name == "TObjString":
@@ -310,3 +419,17 @@
 
     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
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/capi/cling_capi.py
@@ -0,0 +1,69 @@
+import py, os
+
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.lltypesystem import rffi
+from rpython.rlib import libffi, rdynload
+
+__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"], "interpreter/cling/include"),
+                       os.path.join(os.environ["ROOTSYS"], "interpreter/llvm/inst/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 'Cling'
+
+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("clingcwrapper.cxx")],
+    include_dirs=[incpath] + rootincpath,
+    includes=["clingcwrapper.h"],
+    library_dirs=rootlibpath,
+    libraries=["Cling"],
+    compile_extra=["-fno-strict-aliasing"],
+    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):
+    pch = _c_load_dictionary(name)
+    return pch
+
+
+# Cling-specific pythonizations
+def register_pythonizations(space):
+    "NOT_RPYTHON"
+    pass
+
+def pythonize(space, name, w_pycppclass):
+    pass
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
@@ -214,15 +214,22 @@
 
             'charp2stdstring'          : ([c_ccharp],                 c_object),
             'stdstring2stdstring'      : ([c_object],                 c_object),
-            'assign2stdstring'         : ([c_object, c_ccharp],       c_void),
-            'free_stdstring'           : ([c_object],                 c_void),
         }
 
+        # size/offset are backend-specific but fixed after load
+        self.c_sizeof_farg = 0
+        self.c_offset_farg = 0
+
+
 def load_reflection_library(space):
     state = space.fromcache(State)
     if state.library is None:
         from pypy.module._cffi_backend.libraryobj import W_Library
         state.library = W_Library(space, reflection_library, rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY)
+        if state.library:
+            # fix constants
+            state.c_sizeof_farg = _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', []))
+            state.c_offset_farg = _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', []))
     return state.library
 
 def verify_backend(space):
@@ -342,12 +349,12 @@
     return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)]))
 def c_deallocate_function_args(space, cargs):
     call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)])
- at jit.elidable
 def c_function_arg_sizeof(space):
-    return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', []))
- at jit.elidable
+    state = space.fromcache(State)
+    return state.c_sizeof_farg
 def c_function_arg_typeoffset(space):
-    return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', []))
+    state = space.fromcache(State)
+    return state.c_offset_farg
 
 # scope reflection information -----------------------------------------------
 def c_is_namespace(space, scope):
@@ -367,13 +374,12 @@
 def c_base_name(space, cppclass, base_index):
     args = [_Arg(l=cppclass.handle), _Arg(l=base_index)]
     return charp2str_free(space, call_capi(space, 'base_name', args))
- at jit.elidable_promote('2')
 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(l=derived.handle), _Arg(l=base.handle)]))
 
- at jit.elidable_promote('1,2,4')
 def _c_base_offset(space, derived_h, base_h, address, direction):
     args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)]
     return _cdata_to_size_t(space, call_capi(space, 'base_offset', args))
@@ -504,11 +510,6 @@
     return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)]))
 def c_stdstring2stdstring(space, cppobject):
     return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)]))
-def c_assign2stdstring(space, cppobject, svalue):
-    args = [_Arg(l=cppobject), _Arg(s=svalue)]
-    call_capi(space, 'assign2stdstring', args)
-def c_free_stdstring(space, cppobject):
-    call_capi(space, 'free_stdstring', [_Arg(l=cppobject)])
 
 # loadable-capi-specific pythonizations (none, as the capi isn't known until runtime)
 def register_pythonizations(space):
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
@@ -6,8 +6,8 @@
 from rpython.rlib.rarithmetic import r_singlefloat
 from rpython.rlib import jit_libffi, rfloat
 
-from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
-from pypy.module._rawffi.array import W_Array
+from pypy.module._rawffi.interp_rawffi import letter2tp
+from pypy.module._rawffi.array import W_Array, W_ArrayInstance
 
 from pypy.module.cppyy import helper, capi, ffitypes
 
@@ -47,21 +47,35 @@
         return rawobject
     return capi.C_NULL_OBJECT
 
+def is_nullpointer_specialcase(space, w_obj):
+    # 0, None, and nullptr may serve as "NULL", check for any of them
+
+    # integer 0
+    try:
+        return space.int_w(w_obj) == 0
+    except Exception:
+        pass
+    # None or nullptr
+    from pypy.module.cppyy import interp_cppyy
+    return space.is_true(space.is_(w_obj, space.w_None)) or \
+        space.is_true(space.is_(w_obj, interp_cppyy.get_nullptr(space)))
+
 def get_rawbuffer(space, w_obj):
+    # raw buffer
     try:
         buf = space.buffer_w(w_obj)
         return rffi.cast(rffi.VOIDP, buf.get_raw_address())
     except Exception:
         pass
-    # special case: allow integer 0 as NULL
+    # array type
     try:
-        buf = space.int_w(w_obj)
-        if buf == 0:
-            return rffi.cast(rffi.VOIDP, 0)
+        arr = space.interp_w(W_ArrayInstance, w_obj, can_be_None=True)
+        if arr:
+            return rffi.cast(rffi.VOIDP, space.uint_w(arr.getbuffer(space)))
     except Exception:
         pass
-    # special case: allow None as NULL
-    if space.is_true(space.is_(w_obj, space.w_None)):
+    # pre-defined NULL
+    if is_nullpointer_specialcase(space, w_obj):
         return rffi.cast(rffi.VOIDP, 0)
     raise TypeError("not an addressable buffer")
 
@@ -118,7 +132,7 @@
     def __getattr__(self, name):
         if name.startswith('array_'):
             typecode = name[len('array_'):]
-            arr = self.space.interp_w(W_Array, unpack_simple_shape(self.space, self.space.wrap(typecode)))
+            arr = self.space.interp_w(W_Array, letter2tp(self.space, typecode))
             setattr(self, name, arr)
             return arr
         raise AttributeError(name)
@@ -139,8 +153,6 @@
             self.size = array_size
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
-        if hasattr(space, "fake"):
-            raise NotImplementedError
         # read access, so no copy needed
         address_value = self._get_raw_address(space, w_obj, offset)
         address = rffi.cast(rffi.ULONG, address_value)
@@ -261,8 +273,7 @@
         self.name = name
 
     def convert_argument(self, space, w_obj, address, call_local):
-        raise OperationError(space.w_TypeError,
-                             space.wrap('no converter available for type "%s"' % self.name))
+        self._is_abstract(space)
 
 
 class BoolConverter(ffitypes.typeid(bool), TypeConverter):
@@ -372,7 +383,12 @@
         try:
             obj = get_rawbuffer(space, w_obj)
         except TypeError:
-            obj = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
+            try:
+                # TODO: accept a 'capsule' rather than naked int
+                # (do accept int(0), though)
+                obj = rffi.cast(rffi.VOIDP, space.int_w(w_obj))
+            except Exception:
+                obj = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         return obj
 
     def convert_argument(self, space, w_obj, address, call_local):
@@ -385,6 +401,24 @@
         x = rffi.cast(rffi.VOIDPP, address)
         x[0] = self._unwrap_object(space, w_obj)
 
+    def from_memory(self, space, w_obj, w_pycppclass, offset):
+        # returned as a long value for the address (INTPTR_T is not proper
+        # per se, but rffi does not come with a PTRDIFF_T)
+        address = self._get_raw_address(space, w_obj, offset)
+        ptrval = rffi.cast(rffi.ULONG, rffi.cast(rffi.VOIDPP, address)[0])
+        if ptrval == 0:
+            from pypy.module.cppyy import interp_cppyy
+            return interp_cppyy.get_nullptr(space)
+        arr = space.interp_w(W_Array, letter2tp(space, 'P'))
+        return arr.fromaddress(space, ptrval, sys.maxint)
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
+        if is_nullpointer_specialcase(space, w_value):
+            address[0] = rffi.cast(rffi.VOIDP, 0)
+        else:
+            address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
+
 class VoidPtrPtrConverter(TypeConverter):
     _immutable_fields_ = ['uses_local']
 
@@ -412,7 +446,7 @@
     _immutable_fields_ = ['uses_local']
     uses_local = True
 
-class InstancePtrConverter(TypeConverter):
+class InstanceRefConverter(TypeConverter):
     _immutable_fields_ = ['libffitype', 'cppclass']
 
     libffitype  = jit_libffi.types.pointer
@@ -444,17 +478,7 @@
         x = rffi.cast(rffi.VOIDPP, address)
         x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
 
-    def from_memory(self, space, w_obj, w_pycppclass, offset):
-        address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
-        from pypy.module.cppyy import interp_cppyy
-        return interp_cppyy.wrap_cppobject(space, address, self.cppclass,
-                                           do_cast=False, is_ref=True)
-
-    def to_memory(self, space, w_obj, w_value, offset):
-        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
-        address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
-
-class InstanceConverter(InstancePtrConverter):
+class InstanceConverter(InstanceRefConverter):
 
     def convert_argument_libffi(self, space, w_obj, address, call_local):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
@@ -468,6 +492,28 @@
     def to_memory(self, space, w_obj, w_value, offset):
         self._is_abstract(space)
 
+
+class InstancePtrConverter(InstanceRefConverter):
+
+    def _unwrap_object(self, space, w_obj):
+        try:
+            return InstanceRefConverter._unwrap_object(self, space, w_obj)
+        except OperationError, e:
+            # if not instance, allow certain special cases
+            if is_nullpointer_specialcase(space, w_obj):
+                return capi.C_NULL_OBJECT
+            raise e
+
+    def from_memory(self, space, w_obj, w_pycppclass, offset):
+        address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
+        from pypy.module.cppyy import interp_cppyy
+        return interp_cppyy.wrap_cppobject(space, address, self.cppclass,
+                                           do_cast=False, is_ref=True)
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
+        address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
+
 class InstancePtrPtrConverter(InstancePtrConverter):
     _immutable_fields_ = ['uses_local']
 
@@ -487,12 +533,6 @@
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
-    def from_memory(self, space, w_obj, w_pycppclass, offset):
-        self._is_abstract(space)
-
-    def to_memory(self, space, w_obj, w_value, offset):
-        self._is_abstract(space)
-
     def finalize_call(self, space, w_obj, call_local):
         from pypy.module.cppyy.interp_cppyy import W_CPPInstance
         assert isinstance(w_obj, W_CPPInstance)
@@ -501,7 +541,6 @@
 
 
 class StdStringConverter(InstanceConverter):
-    _immutable_fields_ = ['cppclass']
 
     def __init__(self, space, extra):
         from pypy.module.cppyy import interp_cppyy
@@ -509,24 +548,25 @@
         InstanceConverter.__init__(self, space, cppclass)
 
     def _unwrap_object(self, space, w_obj):
-        try:
+        from pypy.module.cppyy.interp_cppyy import W_CPPInstance
+        if isinstance(w_obj, W_CPPInstance):
+            arg = InstanceConverter._unwrap_object(self, space, w_obj)
+            return capi.c_stdstring2stdstring(space, arg)
+        else:
             return capi.c_charp2stdstring(space, space.str_w(w_obj))
-        except Exception, e:
-            arg = InstanceConverter._unwrap_object(self, space, w_obj)
-            result = capi.c_stdstring2stdstring(space, arg)
-            return result
 
     def to_memory(self, space, w_obj, w_value, offset):
         try:
             address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
-            capi.c_assign2stdstring(space, address, space.str_w(w_value))
-            return
+            assign = self.cppclass.get_overload("__assign__")
+            from pypy.module.cppyy import interp_cppyy
+            assign.call(
+                interp_cppyy.wrap_cppobject(space, address, self.cppclass, do_cast=False), [w_value])
         except Exception:
-            pass
-        return InstanceConverter.to_memory(self, space, w_obj, w_value, offset)
+            InstanceConverter.to_memory(self, space, w_obj, w_value, offset)
 
     def free_argument(self, space, arg, call_local):
-        capi.c_free_stdstring(space, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
+        capi.c_destruct(space, self.cppclass, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
 
 class StdStringRefConverter(InstancePtrConverter):
     _immutable_fields_ = ['cppclass']
@@ -570,6 +610,7 @@
     def free_argument(self, space, arg, call_local):
         if hasattr(space, "fake"):
             raise NotImplementedError
+        space.getbuiltinmodule("cpyext")
         from pypy.module.cpyext.pyobject import Py_DecRef, PyObject
         Py_DecRef(space, rffi.cast(PyObject, rffi.cast(rffi.VOIDPP, arg)[0]))
 
@@ -627,8 +668,10 @@
         # type check for the benefit of the annotator
         from pypy.module.cppyy.interp_cppyy import W_CPPClass
         cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
-        if compound == "*" or compound == "&":
+        if compound == "*":
             return InstancePtrConverter(space, cppclass)
+        elif compound == "&":
+            return InstanceRefConverter(space, cppclass)
         elif compound == "**":
             return InstancePtrPtrConverter(space, cppclass)
         elif compound == "":
@@ -654,7 +697,7 @@
 _converters["void**"]                   = VoidPtrPtrConverter
 _converters["void*&"]                   = VoidPtrRefConverter
 
-# special cases (note: CINT backend requires the simple name 'string')
+# special cases (note: 'string' aliases added below)
 _converters["std::basic_string<char>"]           = StdStringConverter
 _converters["const std::basic_string<char>&"]    = StdStringConverter     # TODO: shouldn't copy
 _converters["std::basic_string<char>&"]          = StdStringRefConverter
@@ -776,3 +819,27 @@
     for c_type, alias in aliases:
         _converters[alias] = _converters[c_type]
 _add_aliased_converters()
+
+# ROOT-specific converters (TODO: this is a general use case and should grow
+# an API; putting it here is done only to circumvent circular imports)
+if capi.identify() == "CINT":
+
+    class TStringConverter(InstanceConverter):
+        def __init__(self, space, extra):
+            from pypy.module.cppyy import interp_cppyy
+            cppclass = interp_cppyy.scope_byname(space, "TString")
+            InstanceConverter.__init__(self, space, cppclass)
+
+        def _unwrap_object(self, space, w_obj):
+            from pypy.module.cppyy import interp_cppyy
+            if isinstance(w_obj, interp_cppyy.W_CPPInstance):
+                arg = InstanceConverter._unwrap_object(self, space, w_obj)
+                return capi.backend.c_TString2TString(space, arg)
+            else:
+                return capi.backend.c_charp2TString(space, space.str_w(w_obj))
+
+        def free_argument(self, space, arg, call_local):
+            capi.c_destruct(space, self.cppclass, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
+
+    _converters["TString"]        = TStringConverter
+    _converters["const TString&"] = TStringConverter
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -53,17 +53,12 @@
         if hasattr(space, "fake"):
             raise NotImplementedError
         lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
-        address = rffi.cast(rffi.ULONG, lresult)
+        ptrval = rffi.cast(rffi.ULONG, lresult)
         arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap(self.typecode)))
-        if address == 0:
-            # TODO: fix this hack; fromaddress() will allocate memory if address
-            # is null and there seems to be no way around it (ll_buffer can not
-            # be touched directly)
-            nullarr = arr.fromaddress(space, address, 0)
-            assert isinstance(nullarr, W_ArrayInstance)
-            nullarr.free(space)
-            return nullarr
-        return arr.fromaddress(space, address, sys.maxint)
+        if ptrval == 0:
+            from pypy.module.cppyy import interp_cppyy
+            return interp_cppyy.get_nullptr(space)
+        return arr.fromaddress(space, ptrval, sys.maxint)
 
 
 class VoidExecutor(FunctionExecutor):
@@ -144,7 +139,7 @@
         from pypy.module.cppyy import interp_cppyy
         newthis = capi.c_constructor(space, cppmethod, cpptype, num_args, args)
         assert lltype.typeOf(newthis) == capi.C_OBJECT
-        return space.wrap(newthis)
+        return space.wrap(rffi.cast(rffi.LONG, newthis))   # really want ptrdiff_t here
 
 
 class InstancePtrExecutor(FunctionExecutor):
@@ -160,7 +155,8 @@
         from pypy.module.cppyy import interp_cppyy
         long_result = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
         ptr_result = rffi.cast(capi.C_OBJECT, long_result)
-        return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass)
+        pyres = interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass)
+        return pyres
 
     def execute_libffi(self, space, cif_descr, funcaddr, buffer):
         jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
@@ -189,7 +185,7 @@
         long_result = capi.c_call_o(space, cppmethod, cppthis, num_args, args, self.cppclass)
         ptr_result = rffi.cast(capi.C_OBJECT, long_result)
         return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass,
-                                           do_cast=False, python_owns=True)
+                                           do_cast=False, python_owns=True, fresh=True)
 
     def execute_libffi(self, space, cif_descr, funcaddr, buffer):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
@@ -206,6 +202,13 @@
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
+class StdStringRefExecutor(InstancePtrExecutor):
+
+    def __init__(self, space, cppclass):
+        from pypy.module.cppyy import interp_cppyy
+        cppclass = interp_cppyy.scope_byname(space, capi.std_string_name)
+        InstancePtrExecutor.__init__(self, space, cppclass)
+
 
 class PyObjectExecutor(PtrTypeExecutor):
 
@@ -295,12 +298,12 @@
 _executors["void*"]               = PtrTypeExecutor
 _executors["const char*"]         = CStringExecutor
 
-# special cases
+# special cases (note: 'string' aliases added below)
 _executors["constructor"]         = ConstructorExecutor
 
 _executors["std::basic_string<char>"]         = StdStringExecutor
-_executors["const std::basic_string<char>&"]  = StdStringExecutor
-_executors["std::basic_string<char>&"]        = StdStringExecutor    # TODO: shouldn't copy
+_executors["const std::basic_string<char>&"]  = StdStringRefExecutor
+_executors["std::basic_string<char>&"]        = StdStringRefExecutor
 
 _executors["PyObject*"]           = PyObjectExecutor
 
@@ -363,7 +366,11 @@
     "NOT_RPYTHON"
     aliases = (
         ("const char*",                     "char*"),
+
         ("std::basic_string<char>",         "string"),
+        ("const std::basic_string<char>&",  "const string&"),
+        ("std::basic_string<char>&",        "string&"),
+
         ("PyObject*",                       "_object*"),
     )
 
diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h
--- a/pypy/module/cppyy/include/capi.h
+++ b/pypy/module/cppyy/include/capi.h
@@ -89,11 +89,11 @@
     cppyy_index_t cppyy_get_global_operator(
         cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op);
 
-    /* method properties -----------------------------------------------------  */
+    /* method properties ------------------------------------------------------ */
     int cppyy_is_constructor(cppyy_type_t type, cppyy_index_t idx);
     int cppyy_is_staticmethod(cppyy_type_t type, cppyy_index_t idx);
 
-    /* data member reflection information ------------------------------------  */
+    /* data member reflection information ------------------------------------- */
     int cppyy_num_datamembers(cppyy_scope_t scope);
     char* cppyy_datamember_name(cppyy_scope_t scope, int datamember_index);
     char* cppyy_datamember_type(cppyy_scope_t scope, int datamember_index);
@@ -101,7 +101,7 @@
 
     int cppyy_datamember_index(cppyy_scope_t scope, const char* name);
 
-    /* data member properties ------------------------------------------------  */
+    /* data member properties ------------------------------------------------- */
     int cppyy_is_publicdata(cppyy_type_t type, int datamember_index);
     int cppyy_is_staticdata(cppyy_type_t type, int datamember_index);
 
@@ -112,8 +112,6 @@
 
     cppyy_object_t cppyy_charp2stdstring(const char* str);
     cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
-    void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str);
-    void cppyy_free_stdstring(cppyy_object_t ptr);
 
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cppyy/include/cintcwrapper.h b/pypy/module/cppyy/include/cintcwrapper.h
--- a/pypy/module/cppyy/include/cintcwrapper.h
+++ b/pypy/module/cppyy/include/cintcwrapper.h
@@ -11,12 +11,18 @@
     void* cppyy_load_dictionary(const char* lib_name);
 
     /* pythonization helpers */
+    cppyy_object_t cppyy_create_tf1(const char* funcname, unsigned long address,
+        double xmin, double xmax, int npar);
+
     cppyy_object_t cppyy_ttree_Branch(
         void* vtree, const char* branchname, const char* classname,
         void* addobj, int bufsize, int splitlevel);
 
     long long cppyy_ttree_GetEntry(void* vtree, long long entry);
 
+    cppyy_object_t cppyy_charp2TString(const char* str);
+    cppyy_object_t cppyy_TString2TString(cppyy_object_t ptr);
+
 #ifdef __cplusplus
 }
 #endif // ifdef __cplusplus
diff --git a/pypy/module/cppyy/include/clingcwrapper.h b/pypy/module/cppyy/include/clingcwrapper.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/include/clingcwrapper.h
@@ -0,0 +1,37 @@
+#ifndef CPPYY_CLINGCWRAPPER
+#define CPPYY_CLINGCWRAPPER
+
+#include "capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // ifdef __cplusplus
+
+    /* misc helpers */
+    void* cppyy_load_dictionary(const char* lib_name);
+
+#ifdef __cplusplus
+}
+#endif // ifdef __cplusplus
+
+// TODO: pick up from llvm-config --cxxflags
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Wrapper callback: except this to become available from Cling directly
+typedef void (*CPPYY_Cling_Wrapper_t)(void*, int, void**, void*);
+
+#endif // ifndef CPPYY_CLINGCWRAPPER
diff --git a/pypy/module/cppyy/include/cppyy.h b/pypy/module/cppyy/include/cppyy.h
--- a/pypy/module/cppyy/include/cppyy.h
+++ b/pypy/module/cppyy/include/cppyy.h
@@ -17,7 +17,7 @@
 #ifdef __cplusplus
 struct CPPYY_G__p2p {
 #else
-#typedef struct
+typedef struct {
 #endif
   long i;
   int reftype;
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -40,9 +40,28 @@
     def __init__(self, space):
         self.cppscope_cache = {
             "void" : W_CPPClass(space, "void", capi.C_NULL_TYPE) }
+        self.w_nullptr = None
         self.cpptemplate_cache = {}
         self.cppclass_registry = {}
         self.w_clgen_callback = None
+        self.w_fngen_callback = None
+
+def get_nullptr(space):
+    if hasattr(space, "fake"):
+        raise NotImplementedError
+    state = space.fromcache(State)
+    if state.w_nullptr is None:
+        from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
+        from pypy.module._rawffi.array import W_Array, W_ArrayInstance
+        arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap('P')))
+        # TODO: fix this hack; fromaddress() will allocate memory if address
+        # is null and there seems to be no way around it (ll_buffer can not
+        # be touched directly)
+        nullarr = arr.fromaddress(space, rffi.cast(rffi.ULONG, 0), 0)
+        assert isinstance(nullarr, W_ArrayInstance)
+        nullarr.free(space)
+        state.w_nullptr = space.wrap(nullarr)
+    return state.w_nullptr
 
 @unwrap_spec(name=str)
 def resolve_name(space, name):
@@ -101,6 +120,11 @@
     state = space.fromcache(State)
     state.w_clgen_callback = w_callback
 
+ at unwrap_spec(w_callback=W_Root)
+def set_function_generator(space, w_callback):
+    state = space.fromcache(State)
+    state.w_fngen_callback = w_callback
+
 def register_class(space, w_pycppclass):
     w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
     cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
@@ -108,7 +132,7 @@
     # class allows simple aliasing of methods)
     capi.pythonize(space, cppclass.name, w_pycppclass)
     state = space.fromcache(State)
-    state.cppclass_registry[cppclass.handle] = w_pycppclass
+    state.cppclass_registry[rffi.cast(rffi.LONG, cppclass.handle)] = w_pycppclass
 
 
 class W_CPPLibrary(W_Root):
@@ -580,12 +604,10 @@
     def get_returntype(self):
         return self.space.wrap(self.converter.name)
 
-    @jit.elidable_promote()
     def _get_offset(self, cppinstance):
         if cppinstance:
             assert lltype.typeOf(cppinstance.cppclass.handle) == lltype.typeOf(self.scope.handle)
-            offset = self.offset + capi.c_base_offset(self.space,
-                cppinstance.cppclass, self.scope, cppinstance.get_rawobject(), 1)
+            offset = self.offset + cppinstance.cppclass.get_base_offset(cppinstance, self.scope)
         else:
             offset = self.offset
         return offset
@@ -694,7 +716,6 @@
     def get_method_names(self):
         return self.space.newlist([self.space.wrap(name) for name in self.methods])
 
-    @jit.elidable_promote('0')
     def get_overload(self, name):
         try:
             return self.methods[name]
@@ -707,7 +728,6 @@
     def get_datamember_names(self):
         return self.space.newlist([self.space.wrap(name) for name in self.datamembers])
 
-    @jit.elidable_promote('0')
     def get_datamember(self, name):
         try:
             return self.datamembers[name]
@@ -717,7 +737,6 @@
         self.datamembers[name] = new_dm
         return new_dm
 
-    @jit.elidable_promote('0')
     def dispatch(self, name, signature):
         overload = self.get_overload(name)
         sig = '(%s)' % signature
@@ -886,6 +905,10 @@
     def find_datamember(self, name):
         raise self.missing_attribute_error(name)
 
+    def get_base_offset(self, cppinstance, calling_scope):
+        assert self == cppinstance.cppclass
+        return 0
+
     def get_cppthis(self, cppinstance, calling_scope):
         assert self == cppinstance.cppclass
         return cppinstance.get_rawobject()
@@ -917,10 +940,15 @@
 
 class W_ComplexCPPClass(W_CPPClass):
 
-    def get_cppthis(self, cppinstance, calling_scope):
+    def get_base_offset(self, cppinstance, calling_scope):
         assert self == cppinstance.cppclass
         offset = capi.c_base_offset(self.space,
                                     self, calling_scope, cppinstance.get_rawobject(), 1)
+        return offset
+
+    def get_cppthis(self, cppinstance, calling_scope):
+        assert self == cppinstance.cppclass
+        offset = self.get_base_offset(cppinstance, calling_scope)
         return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
 
 W_ComplexCPPClass.typedef = TypeDef(
@@ -1130,19 +1158,23 @@
 def get_pythonized_cppclass(space, handle):
     state = space.fromcache(State)
     try:
-        w_pycppclass = state.cppclass_registry[handle]
+        w_pycppclass = state.cppclass_registry[rffi.cast(rffi.LONG, handle)]
     except KeyError:
         final_name = capi.c_scoped_final_name(space, handle)
         # the callback will cache the class by calling register_class
         w_pycppclass = space.call_function(state.w_clgen_callback, space.wrap(final_name))
     return w_pycppclass
 
+def get_interface_func(space, w_callable, npar):
+    state = space.fromcache(State)
+    return space.call_function(state.w_fngen_callback, w_callable, space.wrap(npar))
+
 def wrap_cppobject(space, rawobject, cppclass,
                    do_cast=True, python_owns=False, is_ref=False, fresh=False):
     rawobject = rffi.cast(capi.C_OBJECT, rawobject)
 
-    # cast to actual cast if requested and possible
-    w_pycppclass = space.w_None
+    # cast to actual if requested and possible
+    w_pycppclass = None
     if do_cast and rawobject:
         actual = capi.c_actual_class(space, cppclass, rawobject)
         if actual != cppclass.handle:
@@ -1158,7 +1190,7 @@
                 # the variables are re-assigned yet)
                 pass
 
-    if space.is_w(w_pycppclass, space.w_None):
+    if w_pycppclass is None:
         w_pycppclass = get_pythonized_cppclass(space, cppclass.handle)
 
     # try to recycle existing object if this one is not newly created
@@ -1174,16 +1206,30 @@
     memory_regulator.register(cppinstance)
     return w_cppinstance
 
- at unwrap_spec(w_cppinstance=W_CPPInstance)
-def addressof(space, w_cppinstance):
-    """Takes a bound C++ instance, returns the raw address."""
-    address = rffi.cast(rffi.LONG, w_cppinstance.get_rawobject())
+def _addressof(space, w_obj):
+    try:
+        # attempt to extract address from array
+        return rffi.cast(rffi.INTPTR_T, converter.get_rawbuffer(space, w_obj))
+    except TypeError:
+        pass
+    # attempt to get address of C++ instance
+    return rffi.cast(rffi.INTPTR_T, converter.get_rawobject(space, w_obj))
+
+ at unwrap_spec(w_obj=W_Root)
+def addressof(space, w_obj):
+    """Takes a bound C++ instance or array, returns the raw address."""
+    address = _addressof(space, w_obj)
     return space.wrap(address)
 
- at unwrap_spec(address=int, owns=bool)
-def bind_object(space, address, w_pycppclass, owns=False):
+ at unwrap_spec(owns=bool, cast=bool)
+def bind_object(space, w_obj, w_pycppclass, owns=False, cast=False):
     """Takes an address and a bound C++ class proxy, returns a bound instance."""
-    rawobject = rffi.cast(capi.C_OBJECT, address)
+    try:
+        # attempt address from array or C++ instance
+        rawobject = rffi.cast(capi.C_OBJECT, _addressof(space, w_obj))
+    except Exception:
+        # accept integer value as address
+        rawobject = rffi.cast(capi.C_OBJECT, space.uint_w(w_obj))
     w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
     if not w_cppclass:
         w_cppclass = scope_byname(space, space.str_w(w_pycppclass))
@@ -1191,4 +1237,4 @@
             raise OperationError(space.w_TypeError,
                 space.wrap("no such class: %s" % space.str_w(w_pycppclass)))
     cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
-    return wrap_cppobject(space, rawobject, cppclass, do_cast=False, python_owns=owns)
+    return wrap_cppobject(space, rawobject, cppclass, do_cast=cast, python_owns=owns)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -55,6 +55,19 @@
 def clgen_callback(name):
     return get_pycppclass(name)
 
+def fngen_callback(func, npar): # todo, some kind of arg transform spec
+    if npar == 0:
+        def wrapper(a0, a1):
+            la0 = [a0[0], a0[1], a0[2], a0[3]]
+            return func(la0)
+        return wrapper
+    else:
+        def wrapper(a0, a1):
+            la0 = [a0[0], a0[1], a0[2], a0[3]]
+            la1 = [a1[i] for i in range(npar)]
+            return func(la0, la1)
+        return wrapper
+
 
 def make_static_function(func_name, cppol):
     def function(*args):
@@ -416,6 +429,9 @@
     # class generator callback
     cppyy._set_class_generator(clgen_callback)
 
+    # function generator callback
+    cppyy._set_function_generator(fngen_callback)
+
     # user interface objects (note the two-step of not calling scope_byname here:
     # creation of global functions may cause the creation of classes in the global
     # namespace, so gbl must exist at that point to cache them)
@@ -431,6 +447,9 @@
     # be the same issue for all typedef'd builtin types
     setattr(gbl, 'unsigned int', int)
 
+    # install nullptr as a unique reference
+    setattr(gbl, 'nullptr', cppyy._get_nullptr())
+
     # install for user access
     cppyy.gbl = gbl
 
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -8,6 +8,7 @@
 
 #include "TApplication.h"
 #include "TInterpreter.h"
+#include "TVirtualMutex.h"
 #include "Getline.h"
 
 #include "TBaseClass.h"
@@ -24,6 +25,8 @@


More information about the pypy-commit mailing list