Author: Hakan Ardo <ha...@debian.org> Branch: Changeset: r54840:699a431ea9a8 Date: 2012-05-01 11:23 +0200 http://bitbucket.org/pypy/pypy/changeset/699a431ea9a8/
Log: merge diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -21,6 +21,26 @@ .. _`llvm`: http://llvm.org/ +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 +generation in python (as opposed to RPython) and this is used to create very +natural "pythonizations" of the bound code. + + Installation ============ @@ -195,10 +215,12 @@ >>>> d = cppyy.gbl.BaseFactory("name", 42, 3.14) >>>> type(d) <class '__main__.Derived'> - >>>> d.m_i - 42 - >>>> d.m_d - 3.14 + >>>> isinstance(d, cppyy.gbl.Base1) + True + >>>> isinstance(d, cppyy.gbl.Base2) + True + >>>> d.m_i, d.m_d + (42, 3.14) >>>> d.m_name == "name" True >>>> @@ -295,6 +317,9 @@ To select a specific virtual method, do like with normal python classes that override methods: select it from the class that you need, rather than calling the method on the instance. + To select a specific overload, use the __dispatch__ special function, which + takes the name of the desired method and its signature (which can be + obtained from the doc string) as arguments. * **namespaces**: Are represented as python classes. Namespaces are more open-ended than classes, so sometimes initial access may diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst --- a/pypy/doc/extending.rst +++ b/pypy/doc/extending.rst @@ -116,13 +116,21 @@ Reflex ====== -This method is only experimental for now, and is being exercised on a branch, -`reflex-support`_, so you will have to build PyPy yourself. +This method is still experimental and is being exercised on a branch, +`reflex-support`_, which adds the `cppyy`_ module. The method works by using the `Reflex package`_ to provide reflection information of the C++ code, which is then used to automatically generate -bindings at runtime, which can then be used from python. +bindings at runtime. +From a python standpoint, there is no difference between generating bindings +at runtime, or having them "statically" generated and available in scripts +or compiled into extension modules: python classes and functions are always +runtime structures, created when a script or module loads. +However, if the backend itself is capable of dynamic behavior, it is a much +better functional match to python, allowing tighter integration and more +natural language mappings. Full details are `available here`_. +.. _`cppyy`: cppyy.html .. _`reflex-support`: cppyy.html .. _`Reflex package`: http://root.cern.ch/drupal/content/reflex .. _`available here`: cppyy.html @@ -130,16 +138,33 @@ Pros ---- -If it works, it is mostly automatic, and hence easy in use. -The bindings can make use of direct pointers, in which case the calls are -very fast. +The cppyy module is written in RPython, which makes it possible to keep the +code execution visible to the JIT all the way to the actual point of call into +C++, thus allowing for a very fast interface. +Reflex is currently in use in large software environments in High Energy +Physics (HEP), across many different projects and packages, and its use can be +virtually completely automated in a production environment. +One of its uses in HEP is in providing language bindings for CPython. +Thus, it is possible to use Reflex to have bound code work on both CPython and +on PyPy. +In the medium-term, Reflex will be replaced by `cling`_, which is based on +`llvm`_. +This will affect the backend only; the python-side interface is expected to +remain the same, except that cling adds a lot of dynamic behavior to C++, +enabling further language integration. + +.. _`cling`: http://root.cern.ch/drupal/content/cling +.. _`llvm`: http://llvm.org/ Cons ---- -C++ is a large language, and these bindings are not yet feature-complete. -Although missing features should do no harm if you don't use them, if you do -need a particular feature, it may be necessary to work around it in python -or with a C++ helper function. +C++ is a large language, and cppyy is not yet feature-complete. +Still, the experience gained in developing the equivalent bindings for CPython +means that adding missing features is a simple matter of engineering, not a +question of research. +The module is written so that currently missing features should do no harm if +you don't use them, if you do need a particular feature, it may be necessary +to work around it in python or with a C++ helper function. Although Reflex works on various platforms, the bindings with PyPy have only been tested on Linux. diff --git a/pypy/module/rctime/test/test_rctime.py b/pypy/module/rctime/test/test_rctime.py --- a/pypy/module/rctime/test/test_rctime.py +++ b/pypy/module/rctime/test/test_rctime.py @@ -64,6 +64,7 @@ def test_localtime(self): import time as rctime + import os raises(TypeError, rctime.localtime, "foo") rctime.localtime() rctime.localtime(None) @@ -75,6 +76,10 @@ assert 0 <= (t1 - t0) < 1.2 t = rctime.time() assert rctime.localtime(t) == rctime.localtime(t) + if os.name == 'nt': + raises(ValueError, rctime.localtime, -1) + else: + rctime.localtime(-1) def test_mktime(self): import time as rctime @@ -108,8 +113,8 @@ assert long(rctime.mktime(rctime.gmtime(t))) - rctime.timezone == long(t) ltime = rctime.localtime() assert rctime.mktime(tuple(ltime)) == rctime.mktime(ltime) - - assert rctime.mktime(rctime.localtime(-1)) == -1 + if os.name != 'nt': + assert rctime.mktime(rctime.localtime(-1)) == -1 def test_asctime(self): import time as rctime diff --git a/pypy/module/select/__init__.py b/pypy/module/select/__init__.py --- a/pypy/module/select/__init__.py +++ b/pypy/module/select/__init__.py @@ -2,6 +2,7 @@ from pypy.interpreter.mixedmodule import MixedModule import sys +import os class Module(MixedModule): @@ -9,11 +10,13 @@ } interpleveldefs = { - 'poll' : 'interp_select.poll', 'select': 'interp_select.select', 'error' : 'space.fromcache(interp_select.Cache).w_error' } + if os.name =='posix': + interpleveldefs['poll'] = 'interp_select.poll' + if sys.platform.startswith('linux'): interpleveldefs['epoll'] = 'interp_epoll.W_Epoll' from pypy.module.select.interp_epoll import cconfig, public_symbols diff --git a/pypy/module/select/test/test_select.py b/pypy/module/select/test/test_select.py --- a/pypy/module/select/test/test_select.py +++ b/pypy/module/select/test/test_select.py @@ -214,6 +214,8 @@ def test_poll(self): import select + if not hasattr(select, 'poll'): + skip("no select.poll() on this platform") readend, writeend = self.getpair() try: class A(object): diff --git a/pypy/rlib/debug.py b/pypy/rlib/debug.py --- a/pypy/rlib/debug.py +++ b/pypy/rlib/debug.py @@ -1,10 +1,12 @@ import sys, time from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.rarithmetic import is_valid_int def ll_assert(x, msg): """After translation to C, this becomes an RPyAssert.""" + assert type(x) is bool, "bad type! got %r" % (type(x),) assert x, msg class Entry(ExtRegistryEntry): @@ -21,8 +23,13 @@ hop.exception_cannot_occur() hop.genop('debug_assert', vlist) +class FatalError(Exception): + pass + def fatalerror(msg): # print the RPython traceback and abort with a fatal error + if not we_are_translated(): + raise FatalError(msg) from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop llop.debug_print_traceback(lltype.Void) @@ -33,6 +40,8 @@ def fatalerror_notb(msg): # a variant of fatalerror() that doesn't print the RPython traceback + if not we_are_translated(): + raise FatalError(msg) from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop llop.debug_fatalerror(lltype.Void, msg) diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -916,7 +916,7 @@ ll_assert(not self.is_in_nursery(obj), "object in nursery after collection") # similarily, all objects should have this flag: - ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS, + ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0, "missing GCFLAG_TRACK_YOUNG_PTRS") # the GCFLAG_VISITED should not be set between collections ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0, diff --git a/pypy/rpython/memory/gc/semispace.py b/pypy/rpython/memory/gc/semispace.py --- a/pypy/rpython/memory/gc/semispace.py +++ b/pypy/rpython/memory/gc/semispace.py @@ -640,7 +640,7 @@ between collections.""" tid = self.header(obj).tid if tid & GCFLAG_EXTERNAL: - ll_assert(tid & GCFLAG_FORWARDED, "bug: external+!forwarded") + ll_assert(tid & GCFLAG_FORWARDED != 0, "bug: external+!forwarded") ll_assert(not (self.tospace <= obj < self.free), "external flag but object inside the semispaces") else: diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py --- a/pypy/rpython/memory/gctransform/framework.py +++ b/pypy/rpython/memory/gctransform/framework.py @@ -8,7 +8,6 @@ from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rlib.rarithmetic import ovfcheck from pypy.rlib import rgc -from pypy.rlib.debug import ll_assert from pypy.rlib.objectmodel import we_are_translated from pypy.translator.backendopt import graphanalyze from pypy.translator.backendopt.support import var_needsgc _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit