diff --git a/doc/Jamfile b/doc/Jamfile
index 94296899..48a10c14 100644
--- a/doc/Jamfile
+++ b/doc/Jamfile
@@ -9,14 +9,15 @@ path-constant images : html/images ;
project python/doc
- : requirements html:boost.defaults=Boost
+ : requirements html:boost.defaults=none
html:toc.max.depth=3
- html:toc.section.depth=3
- html:chunk.section.depth=3
+ html:toc.section.depth=2
+ html:chunk.section.depth=1
;
import boostbook ;
import quickbook ;
+import docutils ;
boostbook python : python.qbk
: html:$(here)/html
@@ -39,3 +40,8 @@ boostbook reference : reference.qbk
html:boost.image.src=../images/boost.png
html:boost.graphics.root=../images/
;
+
+html article : article.rst
+ : html
+ "--link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css"
+ ;
diff --git a/doc/PyConDC_2003/bpl.html b/doc/PyConDC_2003/bpl.html
deleted file mode 100755
index 32b655bd..00000000
--- a/doc/PyConDC_2003/bpl.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading: “Building Hybrid Systems With Boost.Python”
-
-
-
- Loading...; if nothing happens, please go to http://www.boost-consulting.com/writing/bpl.html.
-
-
-
diff --git a/doc/PyConDC_2003/bpl.pdf b/doc/PyConDC_2003/bpl.pdf
deleted file mode 100755
index 09827aff..00000000
Binary files a/doc/PyConDC_2003/bpl.pdf and /dev/null differ
diff --git a/doc/PyConDC_2003/bpl_mods.txt b/doc/PyConDC_2003/bpl_mods.txt
deleted file mode 100644
index d42f00f8..00000000
--- a/doc/PyConDC_2003/bpl_mods.txt
+++ /dev/null
@@ -1,911 +0,0 @@
-Copyright David Abrahams 2006. Distributed under the Boost
-Software License, Version 1.0. (See accompanying
-file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-.. This is a comment. Note how any initial comments are moved by
- transforms to after the document title, subtitle, and docinfo.
-
-.. Need intro and conclusion
-.. Exposing classes
- .. Constructors
- .. Overloading
- .. Properties and data members
- .. Inheritance
- .. Operators and Special Functions
- .. Virtual Functions
-.. Call Policies
-
-++++++++++++++++++++++++++++++++++++++++++++++
- Introducing Boost.Python (Extended Abstract)
-++++++++++++++++++++++++++++++++++++++++++++++
-
-
-.. bibliographic fields (which also require a transform):
-
-:Author: David Abrahams
-:Address: 45 Walnut Street
- Somerville, MA 02143
-:Contact: dave@boost-consulting.com
-:organization: `Boost Consulting`_
-:status: This is a "work in progress"
-:version: 1
-:copyright: Copyright David Abrahams 2002. All rights reserved
-
-:Dedication:
-
- For my girlfriend, wife, and partner Luann
-
-:abstract:
-
- This paper describes the Boost.Python library, a system for
- C++/Python interoperability.
-
-.. meta::
- :keywords: Boost,python,Boost.Python,C++
- :description lang=en: C++/Python interoperability with Boost.Python
-
-.. contents:: Table of Contents
-.. section-numbering::
-
-
-.. _`Boost Consulting`: http://www.boost-consulting.com
-
-==============
- Introduction
-==============
-
-Python and C++ are in many ways as different as two languages could
-be: while C++ is usually compiled to machine-code, Python is
-interpreted. Python's dynamic type system is often cited as the
-foundation of its flexibility, while in C++ static typing is the
-cornerstone of its efficiency. C++ has an intricate and difficult
-meta-language to support compile-time polymorphism, while Python is
-a uniform language with convenient runtime polymorphism.
-
-Yet for many programmers, these very differences mean that Python and
-C++ complement one another perfectly. Performance bottlenecks in
-Python programs can be rewritten in C++ for maximal speed, and
-authors of powerful C++ libraries choose Python as a middleware
-language for its flexible system integration capabilities.
-Furthermore, the surface differences mask some strong similarities:
-
-* 'C'-family control structures (if, while, for...)
-
-* Support for object-orientation, functional programming, and generic
- programming (these are both *multi-paradigm* programming languages.)
-
-* Comprehensive operator overloading facilities, recognizing the
- importance of syntactic variability for readability and
- expressivity.
-
-* High-level concepts such as collections and iterators.
-
-* High-level encapsulation facilities (C++: namespaces, Python: modules)
- to support the design of re-usable libraries.
-
-* Exception-handling for effective management of error conditions.
-
-* C++ idioms in common use, such as handle/body classes and
- reference-counted smart pointers mirror Python reference semantics.
-
-Python provides a rich 'C' API for writers of 'C' extension modules.
-Unfortunately, using this API directly for exposing C++ type and
-function interfaces to Python is much more tedious than it should be.
-This is mainly due to the limitations of the 'C' language. Compared to
-C++ and Python, 'C' has only very rudimentary abstraction facilities.
-Support for exception-handling is completely missing. One important
-undesirable consequence is that 'C' extension module writers are
-required to manually manage Python reference counts. Another unpleasant
-consequence is a very high degree of repetition of similar code in 'C'
-extension modules. Of course highly redundant code does not only cause
-frustration for the module writer, but is also very difficult to
-maintain.
-
-The limitations of the 'C' API have lead to the development of a
-variety of wrapping systems. SWIG_ is probably the most popular package
-for the integration of C/C++ and Python. A more recent development is
-the SIP_ package, which is specifically designed for interfacing Python
-with the Qt_ graphical user interface library. Both SWIG and SIP
-introduce a new specialized language for defining the inter-language
-bindings. Of course being able to use a specialized language has
-advantages, but having to deal with three different languages (Python,
-C/C++ and the interface language) also introduces practical and mental
-difficulties. The CXX_ package demonstrates an interesting alternative.
-It shows that at least some parts of Python's 'C' API can be wrapped
-and presented through a much more user-friendly C++ interface. However,
-unlike SWIG and SIP, CXX does not include support for wrapping C++
-classes as new Python types. CXX is also no longer actively developed.
-
-In some respects Boost.Python combines ideas from SWIG and SIP with
-ideas from CXX. Like SWIG and SIP, Boost.Python is a system for
-wrapping C++ classes as new Python "built-in" types, and C/C++
-functions as Python functions. Like CXX, Boost.Python presents Python's
-'C' API through a C++ interface. Boost.Python goes beyond the scope of
-other systems with the unique support for C++ virtual functions that
-are overrideable in Python, support for organizing extensions as Python
-packages with a central registry for inter-language type conversions,
-and a convenient mechanism for tying into Python's serialization engine
-(pickle). Importantly, all this is achieved without introducing a new
-syntax. Boost.Python leverages the power of C++ meta-programming
-techniques to introspect about the C++ type system, and presents a
-simple, IDL-like C++ interface for exposing C/C++ code in extension
-modules. Boost.Python is a pure C++ library, the inter-language
-bindings are defined in pure C++, and other than a C++ compiler only
-Python itself is required to get started with Boost.Python. Last but
-not least, Boost.Python is an unrestricted open source library. There
-are no strings attached even for commercial applications.
-
-.. _SWIG: http://www.swig.org/
-.. _SIP: http://www.riverbankcomputing.co.uk/sip/index.php
-.. _Qt: http://www.trolltech.com/
-.. _CXX: http://cxx.sourceforge.net/
-
-===========================
- Boost.Python Design Goals
-===========================
-
-The primary goal of Boost.Python is to allow users to expose C++
-classes and functions to Python using nothing more than a C++
-compiler. In broad strokes, the user experience should be one of
-directly manipulating C++ objects from Python.
-
-However, it's also important not to translate all interfaces *too*
-literally: the idioms of each language must be respected. For
-example, though C++ and Python both have an iterator concept, they are
-expressed very differently. Boost.Python has to be able to bridge the
-interface gap.
-
-It must be possible to insulate Python users from crashes resulting
-from trivial misuses of C++ interfaces, such as accessing
-already-deleted objects. By the same token the library should
-insulate C++ users from low-level Python 'C' API, replacing
-error-prone 'C' interfaces like manual reference-count management and
-raw ``PyObject`` pointers with more-robust alternatives.
-
-Support for component-based development is crucial, so that C++ types
-exposed in one extension module can be passed to functions exposed in
-another without loss of crucial information like C++ inheritance
-relationships.
-
-Finally, all wrapping must be *non-intrusive*, without modifying or
-even seeing the original C++ source code. Existing C++ libraries have
-to be wrappable by third parties who only have access to header files
-and binaries.
-
-==========================
- Hello Boost.Python World
-==========================
-
-And now for a preview of Boost.Python, and how it improves on the raw
-facilities offered by Python. Here's a function we might want to
-expose::
-
- char const* greet(unsigned x)
- {
- static char const* const msgs[] = { "hello", "Boost.Python", "world!" };
-
- if (x > 2)
- throw std::range_error("greet: index out of range");
-
- return msgs[x];
- }
-
-To wrap this function in standard C++ using the Python 'C' API, we'd
-need something like this::
-
- extern "C" // all Python interactions use 'C' linkage and calling convention
- {
- // Wrapper to handle argument/result conversion and checking
- PyObject* greet_wrap(PyObject* args, PyObject * keywords)
- {
- int x;
- if (PyArg_ParseTuple(args, "i", &x)) // extract/check arguments
- {
- char const* result = greet(x); // invoke wrapped function
- return PyString_FromString(result); // convert result to Python
- }
- return 0; // error occurred
- }
-
- // Table of wrapped functions to be exposed by the module
- static PyMethodDef methods[] = {
- { "greet", greet_wrap, METH_VARARGS, "return one of 3 parts of a greeting" }
- , { NULL, NULL, 0, NULL } // sentinel
- };
-
- // module initialization function
- DL_EXPORT init_hello()
- {
- (void) Py_InitModule("hello", methods); // add the methods to the module
- }
- }
-
-Now here's the wrapping code we'd use to expose it with Boost.Python::
-
- #include
- using namespace boost::python;
- BOOST_PYTHON_MODULE(hello)
- {
- def("greet", greet, "return one of 3 parts of a greeting");
- }
-
-and here it is in action::
-
- >>> import hello
- >>> for x in range(3):
- ... print hello.greet(x)
- ...
- hello
- Boost.Python
- world!
-
-Aside from the fact that the 'C' API version is much more verbose than
-the BPL one, it's worth noting that it doesn't handle a few things
-correctly:
-
-* The original function accepts an unsigned integer, and the Python
- 'C' API only gives us a way of extracting signed integers. The
- Boost.Python version will raise a Python exception if we try to pass
- a negative number to ``hello.greet``, but the other one will proceed
- to do whatever the C++ implementation does when converting an
- negative integer to unsigned (usually wrapping to some very large
- number), and pass the incorrect translation on to the wrapped
- function.
-
-* That brings us to the second problem: if the C++ ``greet()``
- function is called with a number greater than 2, it will throw an
- exception. Typically, if a C++ exception propagates across the
- boundary with code generated by a 'C' compiler, it will cause a
- crash. As you can see in the first version, there's no C++
- scaffolding there to prevent this from happening. Functions wrapped
- by Boost.Python automatically include an exception-handling layer
- which protects Python users by translating unhandled C++ exceptions
- into a corresponding Python exception.
-
-* A slightly more-subtle limitation is that the argument conversion
- used in the Python 'C' API case can only get that integer ``x`` in
- *one way*. PyArg_ParseTuple can't convert Python ``long`` objects
- (arbitrary-precision integers) which happen to fit in an ``unsigned
- int`` but not in a ``signed long``, nor will it ever handle a
- wrapped C++ class with a user-defined implicit ``operator unsigned
- int()`` conversion. The BPL's dynamic type conversion registry
- allows users to add arbitrary conversion methods.
-
-==================
- Library Overview
-==================
-
-This section outlines some of the library's major features. Except as
-necessary to avoid confusion, details of library implementation are
-omitted.
-
--------------------------------------------
- The fundamental type-conversion mechanism
--------------------------------------------
-
-XXX This needs to be rewritten.
-
-Every argument of every wrapped function requires some kind of
-extraction code to convert it from Python to C++. Likewise, the
-function return value has to be converted from C++ to Python.
-Appropriate Python exceptions must be raised if the conversion fails.
-Argument and return types are part of the function's type, and much of
-this tedium can be relieved if the wrapping system can extract that
-information through introspection.
-
-Passing a wrapped C++ derived class instance to a C++ function
-accepting a pointer or reference to a base class requires knowledge of
-the inheritance relationship and how to translate the address of a base
-class into that of a derived class.
-
-------------------
- Exposing Classes
-------------------
-
-C++ classes and structs are exposed with a similarly-terse interface.
-Given::
-
- struct World
- {
- void set(std::string msg) { this->msg = msg; }
- std::string greet() { return msg; }
- std::string msg;
- };
-
-The following code will expose it in our extension module::
-
- #include
- BOOST_PYTHON_MODULE(hello)
- {
- class_("World")
- .def("greet", &World::greet)
- .def("set", &World::set)
- ;
- }
-
-Although this code has a certain pythonic familiarity, people
-sometimes find the syntax bit confusing because it doesn't look like
-most of the C++ code they're used to. All the same, this is just
-standard C++. Because of their flexible syntax and operator
-overloading, C++ and Python are great for defining domain-specific
-(sub)languages
-(DSLs), and that's what we've done in BPL. To break it down::
-
- class_("World")
-
-constructs an unnamed object of type ``class_`` and passes
-``"World"`` to its constructor. This creates a new-style Python class
-called ``World`` in the extension module, and associates it with the
-C++ type ``World`` in the BPL type conversion registry. We might have
-also written::
-
- class_ w("World");
-
-but that would've been more verbose, since we'd have to name ``w``
-again to invoke its ``def()`` member function::
-
- w.def("greet", &World::greet)
-
-There's nothing special about the location of the dot for member
-access in the original example: C++ allows any amount of whitespace on
-either side of a token, and placing the dot at the beginning of each
-line allows us to chain as many successive calls to member functions
-as we like with a uniform syntax. The other key fact that allows
-chaining is that ``class_<>`` member functions all return a reference
-to ``*this``.
-
-So the example is equivalent to::
-
- class_ w("World");
- w.def("greet", &World::greet);
- w.def("set", &World::set);
-
-It's occasionally useful to be able to break down the components of a
-Boost.Python class wrapper in this way, but the rest of this paper
-will tend to stick to the terse syntax.
-
-For completeness, here's the wrapped class in use:
-
->>> import hello
->>> planet = hello.World()
->>> planet.set('howdy')
->>> planet.greet()
-'howdy'
-
-Constructors
-============
-
-Since our ``World`` class is just a plain ``struct``, it has an
-implicit no-argument (nullary) constructor. Boost.Python exposes the
-nullary constructor by default, which is why we were able to write:
-
->>> planet = hello.World()
-
-However, well-designed classes in any language may require constructor
-arguments in order to establish their invariants. Unlike Python,
-where ``__init__`` is just a specially-named method, In C++
-constructors cannot be handled like ordinary member functions. In
-particular, we can't take their address: ``&World::World`` is an
-error. The library provides a different interface for specifying
-constructors. Given::
-
- struct World
- {
- World(std::string msg); // added constructor
- ...
-
-we can modify our wrapping code as follows::
-
- class_("World", init())
- ...
-
-of course, a C++ class may have additional constructors, and we can
-expose those as well by passing more instances of ``init<...>`` to
-``def()``::
-
- class_("World", init())
- .def(init())
- ...
-
-Boost.Python allows wrapped functions, member functions, and
-constructors to be overloaded to mirror C++ overloading.
-
-Data Members and Properties
-===========================
-
-Any publicly-accessible data members in a C++ class can be easily
-exposed as either ``readonly`` or ``readwrite`` attributes::
-
- class_("World", init())
- .def_readonly("msg", &World::msg)
- ...
-
-and can be used directly in Python:
-
->>> planet = hello.World('howdy')
->>> planet.msg
-'howdy'
-
-This does *not* result in adding attributes to the ``World`` instance
-``__dict__``, which can result in substantial memory savings when
-wrapping large data structures. In fact, no instance ``__dict__``
-will be created at all unless attributes are explicitly added from
-Python. BPL owes this capability to the new Python 2.2 type system,
-in particular the descriptor interface and ``property`` type.
-
-In C++, publicly-accessible data members are considered a sign of poor
-design because they break encapsulation, and style guides usually
-dictate the use of "getter" and "setter" functions instead. In
-Python, however, ``__getattr__``, ``__setattr__``, and since 2.2,
-``property`` mean that attribute access is just one more
-well-encapsulated syntactic tool at the programmer's disposal. BPL
-bridges this idiomatic gap by making Python ``property`` creation
-directly available to users. So if ``msg`` were private, we could
-still expose it as attribute in Python as follows::
-
- class_("World", init())
- .add_property("msg", &World::greet, &World::set)
- ...
-
-The example above mirrors the familiar usage of properties in Python
-2.2+:
-
->>> class World(object):
-... __init__(self, msg):
-... self.__msg = msg
-... def greet(self):
-... return self.__msg
-... def set(self, msg):
-... self.__msg = msg
-... msg = property(greet, set)
-
-Operators and Special Functions
-===============================
-
-The ability to write arithmetic operators for user-defined types that
-C++ and Python both allow the definition of has been a major factor in
-the popularity of both languages for scientific computing. The
-success of packages like NumPy attests to the power of exposing
-operators in extension modules. In this example we'll wrap a class
-representing a position in a large file::
-
- class FilePos { /*...*/ };
-
- // Linear offset
- FilePos operator+(FilePos, int);
- FilePos operator+(int, FilePos);
- FilePos operator-(FilePos, int);
-
- // Distance between two FilePos objects
- int operator-(FilePos, FilePos);
-
- // Offset with assignment
- FilePos& operator+=(FilePos&, int);
- FilePos& operator-=(FilePos&, int);
-
- // Comparison
- bool operator<(FilePos, FilePos);
-
-The wrapping code looks like this::
-
- class_("FilePos")
- .def(self + int()) // __add__
- .def(int() + self) // __radd__
- .def(self - int()) // __sub__
-
- .def(self - self) // __sub__
-
- .def(self += int()) // __iadd__
- .def(self -= int()) // __isub__
-
- .def(self < self); // __lt__
- ;
-
-The magic is performed using a simplified application of "expression
-templates" [VELD1995]_, a technique originally developed by for
-optimization of high-performance matrix algebra expressions. The
-essence is that instead of performing the computation immediately,
-operators are overloaded to construct a type *representing* the
-computation. In matrix algebra, dramatic optimizations are often
-available when the structure of an entire expression can be taken into
-account, rather than processing each operation "greedily".
-Boost.Python uses the same technique to build an appropriate Python
-callable object based on an expression involving ``self``, which is
-then added to the class.
-
-Inheritance
-===========
-
-C++ inheritance relationships can be represented to Boost.Python by adding
-an optional ``bases<...>`` argument to the ``class_<...>`` template
-parameter list as follows::
-
- class_ >("Derived")
- ...
-
-This has two effects:
-
-1. When the ``class_<...>`` is created, Python type objects
- corresponding to ``Base1`` and ``Base2`` are looked up in the BPL
- registry, and are used as bases for the new Python ``Derived`` type
- object [#mi]_, so methods exposed for the Python ``Base1`` and
- ``Base2`` types are automatically members of the ``Derived`` type.
- Because the registry is global, this works correctly even if
- ``Derived`` is exposed in a different module from either of its
- bases.
-
-2. C++ conversions from ``Derived`` to its bases are added to the
- Boost.Python registry. Thus wrapped C++ methods expecting (a
- pointer or reference to) an object of either base type can be
- called with an object wrapping a ``Derived`` instance. Wrapped
- member functions of class ``T`` are treated as though they have an
- implicit first argument of ``T&``, so these conversions are
- necessary to allow the base class methods to be called for derived
- objects.
-
-Of course it's possible to derive new Python classes from wrapped C++
-class instances. Because Boost.Python uses the new-style class
-system, that works very much as for the Python built-in types. There
-is one significant detail in which it differs: the built-in types
-generally establish their invariants in their ``__new__`` function, so
-that derived classes do not need to call ``__init__`` on the base
-class before invoking its methods :
-
->>> class L(list):
-... def __init__(self):
-... pass
-...
->>> L().reverse()
->>>
-
-Because C++ object construction is a one-step operation, C++ instance
-data cannot be constructed until the arguments are available, in the
-``__init__`` function:
-
->>> class D(SomeBPLClass):
-... def __init__(self):
-... pass
-...
->>> D().some_bpl_method()
-Traceback (most recent call last):
- File "", line 1, in ?
-TypeError: bad argument type for built-in operation
-
-This happened because Boost.Python couldn't find instance data of type
-``SomeBPLClass`` within the ``D`` instance; ``D``'s ``__init__``
-function masked construction of the base class. It could be corrected
-by either removing ``D``'s ``__init__`` function or having it call
-``SomeBPLClass.__init__(...)`` explicitly.
-
-Virtual Functions
-=================
-
-Deriving new types in Python from extension classes is not very
-interesting unless they can be used polymorphically from C++. In
-other words, Python method implementations should appear to override
-the implementation of C++ virtual functions when called *through base
-class pointers/references from C++*. Since the only way to alter the
-behavior of a virtual function is to override it in a derived class,
-the user must build a special derived class to dispatch a polymorphic
-class' virtual functions::
-
- //
- // interface to wrap:
- //
- class Base
- {
- public:
- virtual int f(std::string x) { return 42; }
- virtual ~Base();
- };
-
- int calls_f(Base const& b, std::string x) { return b.f(x); }
-
- //
- // Wrapping Code
- //
-
- // Dispatcher class
- struct BaseWrap : Base
- {
- // Store a pointer to the Python object
- BaseWrap(PyObject* self_) : self(self_) {}
- PyObject* self;
-
- // Default implementation, for when f is not overridden
- int f_default(std::string x) { return this->Base::f(x); }
- // Dispatch implementation
- int f(std::string x) { return call_method(self, "f", x); }
- };
-
- ...
- def("calls_f", calls_f);
- class_("Base")
- .def("f", &Base::f, &BaseWrap::f_default)
- ;
-
-Now here's some Python code which demonstrates:
-
->>> class Derived(Base):
-... def f(self, s):
-... return len(s)
-...
->>> calls_f(Base(), 'foo')
-42
->>> calls_f(Derived(), 'forty-two')
-9
-
-Things to notice about the dispatcher class:
-
-* The key element which allows overriding in Python is the
- ``call_method`` invocation, which uses the same global type
- conversion registry as the C++ function wrapping does to convert its
- arguments from C++ to Python and its return type from Python to C++.
-
-* Any constructor signatures you wish to wrap must be replicated with
- an initial ``PyObject*`` argument
-
-* The dispatcher must store this argument so that it can be used to
- invoke ``call_method``
-
-* The ``f_default`` member function is needed when the function being
- exposed is not pure virtual; there's no other way ``Base::f`` can be
- called on an object of type ``BaseWrap``, since it overrides ``f``.
-
-Admittedly, this formula is tedious to repeat, especially on a project
-with many polymorphic classes; that it is necessary reflects
-limitations in C++'s compile-time reflection capabilities. Several
-efforts are underway to write front-ends for Boost.Python which can
-generate these dispatchers (and other wrapping code) automatically.
-If these are successful it will mark a move away from wrapping
-everything directly in pure C++ for many of our users.
-
----------------
- Serialization
----------------
-
-*Serialization* is the process of converting objects in memory to a
-form that can be stored on disk or sent over a network connection. The
-serialized object (most often a plain string) can be retrieved and
-converted back to the original object. A good serialization system will
-automatically convert entire object hierarchies. Python's standard
-``pickle`` module is such a system. It leverages the language's strong
-runtime introspection facilities for serializing practically arbitrary
-user-defined objects. With a few simple and unintrusive provisions this
-powerful machinery can be extended to also work for wrapped C++ objects.
-Here is an example::
-
- #include
-
- struct World
- {
- World(std::string a_msg) : msg(a_msg) {}
- std::string greet() const { return msg; }
- std::string msg;
- };
-
- #include
- using namespace boost::python;
-
- struct World_picklers : pickle_suite
- {
- static tuple
- getinitargs(World const& w) { return make_tuple(w.greet()); }
- };
-
- BOOST_PYTHON_MODULE(hello)
- {
- class_("World", init())
- .def("greet", &World::greet)
- .def_pickle(World_picklers())
- ;
- }
-
-Now let's create a ``World`` object and put it to rest on disk::
-
- >>> import hello
- >>> import pickle
- >>> a_world = hello.World("howdy")
- >>> pickle.dump(a_world, open("my_world", "w"))
-
-In a potentially *different script* on a potentially *different
-computer* with a potentially *different operating system*::
-
- >>> import pickle
- >>> resurrected_world = pickle.load(open("my_world", "r"))
- >>> resurrected_world.greet()
- 'howdy'
-
-Of course the ``cPickle`` module can also be used for faster
-processing.
-
-Boost.Python's ``pickle_suite`` fully supports the ``pickle`` protocol
-defined in the standard Python documentation. There is a one-to-one
-correspondence between the standard pickling methods (``__getinitargs__``,
-``__getstate__``, ``__setstate__``) and the functions defined by the
-user in the class derived from ``pickle_suite`` (``getinitargs``,
-``getstate``, ``setstate``). The ``class_::def_pickle()`` member function
-is used to establish the Python bindings for all user-defined functions
-simultaneously. Correct signatures for these functions are enforced at
-compile time. Non-sensical combinations of the three pickle functions
-are also rejected at compile time. These measures are designed to
-help the user in avoiding obvious errors.
-
-Enabling serialization of more complex C++ objects requires a little
-more work than is shown in the example above. Fortunately the
-``object`` interface (see next section) greatly helps in keeping the
-code manageable.
-
-------------------
- Object interface
-------------------
-
-Experienced extension module authors will be familiar with the 'C' view
-of Python objects, the ubiquitous ``PyObject*``. Most if not all Python
-'C' API functions involve ``PyObject*`` as arguments or return type. A
-major complication is the raw reference counting interface presented to
-the 'C' programmer. E.g. some API functions return *new references* and
-others return *borrowed references*. It is up to the extension module
-writer to properly increment and decrement reference counts. This
-quickly becomes cumbersome and error prone, especially if there are
-multiple execution paths.
-
-Boost.Python provides a type ``object`` which is essentially a high
-level wrapper around ``PyObject*``. ``object`` automates reference
-counting as much as possible. It also provides the facilities for
-converting arbitrary C++ types to Python objects and vice versa.
-This significantly reduces the learning effort for prospective
-extension module writers.
-
-Creating an ``object`` from any other type is extremely simple::
-
- object o(3);
-
-``object`` has templated interactions with all other types, with
-automatic to-python conversions. It happens so naturally that it's
-easily overlooked.
-
-The ``extract`` class template can be used to convert Python objects
-to C++ types::
-
- double x = extract(o);
-
-All registered user-defined conversions are automatically accessible
-through the ``object`` interface. With reference to the ``World`` class
-defined in previous examples::
-
- object as_python_object(World("howdy"));
- World back_as_c_plus_plus_object = extract(as_python_object);
-
-If a C++ type cannot be converted to a Python object an appropriate
-exception is thrown at runtime. Similarly, an appropriate exception is
-thrown if a C++ type cannot be extracted from a Python object.
-``extract`` provides facilities for avoiding exceptions if this is
-desired.
-
-The ``object::attr()`` member function is available for accessing
-and manipulating attributes of Python objects. For example::
-
- object planet(World());
- planet.attr("set")("howdy");
-
-``planet.attr("set")`` returns a callable ``object``. ``"howdy"`` is
-converted to a Python string object which is then passed as an argument
-to the ``set`` method.
-
-The ``object`` type is accompanied by a set of derived types
-that mirror the Python built-in types such as ``list``, ``dict``,
-``tuple``, etc. as much as possible. This enables convenient
-manipulation of these high-level types from C++::
-
- dict d;
- d["some"] = "thing";
- d["lucky_number"] = 13;
- list l = d.keys();
-
-This almost looks and works like regular Python code, but it is pure C++.
-
-=================
- Thinking hybrid
-=================
-
-For many applications runtime performance considerations are very
-important. This is particularly true for most scientific applications.
-Often the performance considerations dictate the use of a compiled
-language for the core algorithms. Traditionally the decision to use a
-particular programming language is an exclusive one. Because of the
-practical and mental difficulties of combining different languages many
-systems are written in just one language. This is quite unfortunate
-because the price payed for runtime performance is typically a
-significant overhead due to static typing. For example, our experience
-shows that developing maintainable C++ code is typically much more
-time-consuming and requires much more hard-earned working experience
-than developing useful Python code. A related observation is that many
-compiled packages are augmented by some type of rudimentary scripting
-layer. These ad hoc solutions clearly show that many times a compiled
-language alone does not get the job done. On the other hand it is also
-clear that a pure Python implementation is too slow for numerically
-intensive production code.
-
-Boost.Python enables us to *think hybrid* when developing new
-applications. Python can be used for rapidly prototyping a
-new application. Python's ease of use and the large pool of standard
-libraries give us a head start on the way to a first working system. If
-necessary, the working procedure can be used to discover the
-rate-limiting algorithms. To maximize performance these can be
-reimplemented in C++, together with the Boost.Python bindings needed to
-tie them back into the existing higher-level procedure.
-
-Of course, this *top-down* approach is less attractive if it is clear
-from the start that many algorithms will eventually have to be
-implemented in a compiled language. Fortunately Boost.Python also
-enables us to pursue a *bottom-up* approach. We have used this approach
-very successfully in the development of a toolbox for scientific
-applications (scitbx) that we will describe elsewhere. The toolbox
-started out mainly as a library of C++ classes with Boost.Python
-bindings, and for a while the growth was mainly concentrated on the C++
-parts. However, as the toolbox is becoming more complete, more and more
-newly added functionality can be implemented in Python. We expect this
-trend to continue, as illustrated qualitatively in this figure:
-
-.. image:: python_cpp_mix.png
-
-This figure shows the ratio of newly added C++ and Python code over
-time as new algorithms are implemented. We expect this ratio to level
-out near 70% Python. The increasing ability to solve new problems
-mostly with the easy-to-use Python language rather than a necessarily
-more arcane statically typed language is the return on the investment
-of learning how to use Boost.Python. The ability to solve some problems
-entirely using only Python will enable a larger group of people to
-participate in the rapid development of new applications.
-
-=============
- Conclusions
-=============
-
-The examples in this paper illustrate that Boost.Python enables
-seamless interoperability between C++ and Python. Importantly, this is
-achieved without introducing a third syntax: the Python/C++ interface
-definitions are written in pure C++. This avoids any problems with
-parsing the C++ code to be interfaced to Python, yet the interface
-definitions are concise and maintainable. Freed from most of the
-development-time penalties of crossing a language boundary, software
-designers can take full advantage of two rich and complimentary
-language environments. In practice it turns out that some things are
-very difficult to do with pure Python/C (e.g. an efficient array
-library with an intuitive interface in the compiled language) and
-others are very difficult to do with pure C++ (e.g. serialization).
-If one has the luxury of being able to design a software system as a
-hybrid system from the ground up there are many new ways of avoiding
-road blocks in one language or the other.
-
-.. I'm not ready to give up on all of this quite yet
-
-.. Perhaps one day we'll have a language with the simplicity and
- expressive power of Python and the compile-time muscle of C++. Being
- able to take advantage of all of these facilities without paying the
- mental and development-time penalties of crossing a language barrier
- would bring enormous benefits. Until then, interoperability tools
- like Boost.Python can help lower the barrier and make the benefits of
- both languages more accessible to both communities.
-
-===========
- Footnotes
-===========
-
-.. [#mi] For hard-core new-style class/extension module writers it is
- worth noting that the normal requirement that all extension classes
- with data form a layout-compatible single-inheritance chain is
- lifted for Boost.Python extension classes. Clearly, either
- ``Base1`` or ``Base2`` has to occupy a different offset in the
- ``Derived`` class instance. This is possible because the wrapped
- part of BPL extension class instances is never assumed to have a
- fixed offset within the wrapper.
-
-===========
- Citations
-===========
-
-.. [VELD1995] T. Veldhuizen, "Expression Templates," C++ Report,
- Vol. 7 No. 5 June 1995, pp. 26-31.
- http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
diff --git a/doc/PyConDC_2003/default.css b/doc/PyConDC_2003/default.css
deleted file mode 100644
index f8109bbd..00000000
--- a/doc/PyConDC_2003/default.css
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-:Author: David Goodger
-:Contact: goodger@users.sourceforge.net
-:copyright: This stylesheet has been placed in the public domain.
-
-boostinspect:nolicense
-
-Default cascading style sheet for the HTML output of Docutils.
-*/
-
-.first {
- margin-top: 0 }
-
-.last {
- margin-bottom: 0 }
-
-a.toc-backref {
- text-decoration: none ;
- color: black }
-
-dd {
- margin-bottom: 0.5em }
-
-div.abstract {
- margin: 2em 5em }
-
-div.abstract p.topic-title {
- font-weight: bold ;
- text-align: center }
-
-div.attention, div.caution, div.danger, div.error, div.hint,
-div.important, div.note, div.tip, div.warning {
- margin: 2em ;
- border: medium outset ;
- padding: 1em }
-
-div.attention p.admonition-title, div.caution p.admonition-title,
-div.danger p.admonition-title, div.error p.admonition-title,
-div.warning p.admonition-title {
- color: red ;
- font-weight: bold ;
- font-family: sans-serif }
-
-div.hint p.admonition-title, div.important p.admonition-title,
-div.note p.admonition-title, div.tip p.admonition-title {
- font-weight: bold ;
- font-family: sans-serif }
-
-div.dedication {
- margin: 2em 5em ;
- text-align: center ;
- font-style: italic }
-
-div.dedication p.topic-title {
- font-weight: bold ;
- font-style: normal }
-
-div.figure {
- margin-left: 2em }
-
-div.footer, div.header {
- font-size: smaller }
-
-div.system-messages {
- margin: 5em }
-
-div.system-messages h1 {
- color: red }
-
-div.system-message {
- border: medium outset ;
- padding: 1em }
-
-div.system-message p.system-message-title {
- color: red ;
- font-weight: bold }
-
-div.topic {
- margin: 2em }
-
-h1.title {
- text-align: center }
-
-h2.subtitle {
- text-align: center }
-
-hr {
- width: 75% }
-
-ol.simple, ul.simple {
- margin-bottom: 1em }
-
-ol.arabic {
- list-style: decimal }
-
-ol.loweralpha {
- list-style: lower-alpha }
-
-ol.upperalpha {
- list-style: upper-alpha }
-
-ol.lowerroman {
- list-style: lower-roman }
-
-ol.upperroman {
- list-style: upper-roman }
-
-p.caption {
- font-style: italic }
-
-p.credits {
- font-style: italic ;
- font-size: smaller }
-
-p.label {
- white-space: nowrap }
-
-p.topic-title {
- font-weight: bold }
-
-pre.address {
- margin-bottom: 0 ;
- margin-top: 0 ;
- font-family: serif ;
- font-size: 100% }
-
-pre.line-block {
- font-family: serif ;
- font-size: 100% }
-
-pre.literal-block, pre.doctest-block {
- margin-left: 2em ;
- margin-right: 2em ;
- background-color: #eeeeee }
-
-span.classifier {
- font-family: sans-serif ;
- font-style: oblique }
-
-span.classifier-delimiter {
- font-family: sans-serif ;
- font-weight: bold }
-
-span.interpreted {
- font-family: sans-serif }
-
-span.option-argument {
- font-style: italic }
-
-span.pre {
- white-space: pre }
-
-span.problematic {
- color: red }
-
-table {
- margin-top: 0.5em ;
- margin-bottom: 0.5em }
-
-table.citation {
- border-left: solid thin gray ;
- padding-left: 0.5ex }
-
-table.docinfo {
- margin: 2em 4em }
-
-table.footnote {
- border-left: solid thin black ;
- padding-left: 0.5ex }
-
-td, th {
- padding-left: 0.5em ;
- padding-right: 0.5em ;
- vertical-align: top }
-
-th.docinfo-name, th.field-name {
- font-weight: bold ;
- text-align: left ;
- white-space: nowrap }
-
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
- font-size: 100% }
-
-tt {
- background-color: #eeeeee }
-
-ul.auto-toc {
- list-style-type: none }
diff --git a/doc/PyConDC_2003/python_cpp_mix.jpg b/doc/PyConDC_2003/python_cpp_mix.jpg
deleted file mode 100755
index 755a9605..00000000
Binary files a/doc/PyConDC_2003/python_cpp_mix.jpg and /dev/null differ
diff --git a/doc/PyConDC_2003/bpl.txt b/doc/article.rst
similarity index 99%
rename from doc/PyConDC_2003/bpl.txt
rename to doc/article.rst
index c2ee19aa..521f04f4 100644
--- a/doc/PyConDC_2003/bpl.txt
+++ b/doc/article.rst
@@ -5,7 +5,7 @@
:Author: David Abrahams
:Contact: dave@boost-consulting.com
:organization: `Boost Consulting`_
-:date: $Date$
+:date: 2003-05-14
:Author: Ralf W. Grosse-Kunstleve
@@ -808,7 +808,7 @@ mainly concentrated on the C++ parts. However, as the toolbox is
becoming more complete, more and more newly added functionality can be
implemented in Python.
-.. image:: python_cpp_mix.jpg
+.. image:: images/python_cpp_mix.png
This figure shows the estimated ratio of newly added C++ and Python
code over time as new algorithms are implemented. We expect this
diff --git a/doc/boost.css b/doc/boost.css
deleted file mode 100644
index 6c3e9808..00000000
--- a/doc/boost.css
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright David Abrahams 2006. Distributed under the Boost
- Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-*/
-H1
-{
- FONT-SIZE: 200%
- COLOR: #00007f
-}
-H2
-{
- FONT-SIZE: 150%;
-}
-H3
-{
- FONT-SIZE: 125%;
-}
-H4
-{
- FONT-SIZE: 108%;
-}
-BODY
-{
- FONT-SIZE: 100%;
- BACKGROUND-COLOR: #ffffff
-}
-PRE
-{
- MARGIN-LEFT: 2pc;
- FONT-SIZE: 80%;
- BACKGROUND-COLOR: #dfffff
-}
-CODE
-{
- FONT-SIZE: 95%;
- white-space: pre
-}
-.index
-{
- TEXT-ALIGN: left
-}
-.page-index
-{
- TEXT-ALIGN: left
-}
-.definition
-{
- TEXT-ALIGN: left
-}
-.footnote
-{
- FONT-SIZE: 66%;
- VERTICAL-ALIGN: super;
- TEXT-DECORATION: none
-}
-.function-semantics
-{
- CLEAR: left
-}
-.metafunction-semantics
-{
- CLEAR: left
-}
diff --git a/doc/building.html b/doc/building.html
deleted file mode 100644
index e2c48847..00000000
--- a/doc/building.html
+++ /dev/null
@@ -1,636 +0,0 @@
-
-
-
-
-
-
-Boost C++ Libraries: Boost.Python Build and Test HOWTO
-
-
-
-
There are two basic models for combining C++ and Python:
-
-
extending, in which the end-user launches the Python interpreter
-executable and imports Python “extension modules” written in C++.
-Think of taking a library written in C++ and giving it a Python
-interface so Python programmers can use it. From Python, these
-modules look just like regular Python modules.
-
embedding, in which the end-user launches a program written
-in C++ that in turn invokes the Python interpreter as a library
-subroutine. Think of adding scriptability to an existing
-application.
-
-
The key distinction between extending and embedding is the location
-of the C++ main() function: in the Python interpreter executable,
-or in some other program, respectively. Note that even when
-embedding Python in another program, extension modules are often
-the best way to make C/C++ functionality accessible to Python
-code, so the use of extension modules is really at the heart of
-both models.
-
Except in rare cases, extension modules are built as
-dynamically-loaded libraries with a single entry point, which means
-you can change them without rebuilding either the other extension
-modules or the executable containing main().
There is no need to “install Boost” in order to get started using
-Boost.Python. These instructions use Boost.Build projects,
-which will build those binaries as soon as they're needed. Your
-first tests may take a little longer while you wait for
-Boost.Python to build, but doing things this way will save you from
-worrying about build intricacies like which library binaries to use
-for a specific compiler configuration and figuring out the right
-compiler options to use yourself.
-
-
-
Note
-
Of course it's possible to use other build systems to
-build Boost.Python and its extensions, but they are not
-officially supported by Boost. Moreover 99% of all “I can't
-build Boost.Python” problems come from trying to use another
-build system without first following these instructions.
-
If you want to use another system anyway, we suggest that you
-follow these instructions, and then invoke bjam with the
-
--a-ofilename
-
-
options to dump the build commands it executes to a file, so
-you can see what your alternate build system needs to do.
cd into the libs/python/example/quickstart/ directory of your
-Boost installation, which contains a small example project.
-
-
Invoke bjam. Replace the “stage“ argument from the
-example invocation from section 5 of the Getting Started
-Guide with “test,“ to build all the test targets. Also add
-the argument “--verbose-test” to see the output generated by
-the tests when they are run.
-
On Windows, your bjam invocation might look something like:
-
-C:\boost_1_34_0\…\quickstart> bjam toolset=msvc --verbose-test test
-
-
and on Unix variants, perhaps,
-
-~/boost_1_34_0/…/quickstart$ bjam toolset=gcc --verbose-test test
-
-
-
-
-
Note to Windows Users
-
For the sake of concision, the rest of this guide will use
-unix-style forward slashes in pathnames instead of the
-backslashes with which you may be more familiar. The forward
-slashes should work everywhere except in Command Prompt
-windows, where you should use backslashes.
-
-
If you followed this procedure successfully, you will have built an
-extension module called extending and tested it by running a
-Python script called test_extending.py. You will also have
-built and run a simple application called embedding that embeds
-python.
If you're seeing lots of compiler and/or linker error messages,
-it's probably because Boost.Build is having trouble finding your
-Python installation. You might want to pass the
---debug-configuration option to bjam the first few times
-you invoke it, to make sure that Boost.Build is correctly locating
-all the parts of your Python installation. If it isn't, consider
-Configuring Boost.Build as detailed below.
-
If you're still having trouble, Someone on one of the following
-mailing lists may be able to help:
Rejoice! If you're new to Boost.Python, at this point it might be
-a good idea to ignore build issues for a while and concentrate on
-learning the library by going through the tutorial and perhaps
-some of the reference documentation, trying out what you've
-learned about the API by modifying the quickstart project.
If you're content to keep your extension module forever in one
-source file called extending.cpp, inside your Boost
-distribution, and import it forever as extending, then you can
-stop here. However, it's likely that you will want to make a few
-changes. There are a few things you can do without having to learn
-Boost.Build in depth.
-
The project you just built is specified in two files in the current
-directory: boost-build.jam, which tells bjam where it can
-find the interpreted code of the Boost build system, and
-Jamroot, which describes the targets you just built. These
-files are heavily commented, so they should be easy to modify.
-Take care, however, to preserve whitespace. Punctuation such as
-; will not be recognized as intended by bjam if it is not
-surrounded by whitespace.
-
-
Relocate the Project
-
You'll probably want to copy this project elsewhere so you can
-change it without modifying your Boost distribution. To do that,
-simply
-
-
copy the entire libs/python/example/quickstart/ directory
-into a new directory.
-
In the new copies of boost-build.jam and Jamroot, locate
-the relative path near the top of the file that is clearly
-marked by a comment, and edit that path so that it refers to the
-same directory your Boost distribution as it referred to when
-the file was in its original location in the
-libs/python/example/quickstart/ directory.
-
-
For example, if you moved the project from
-/home/dave/boost_1_34_0/libs/python/example/quickstart to
-/home/dave/my-project, you could change the first path in
-boost-build.jam from
The names of additional source files involved in building your
-extension module or embedding application can be listed in
-Jamroot right alongside extending.cpp or embedding.cpp
-respectively. Just be sure to leave whitespace around each
-filename:
-
-… file1.cpp file2.cpp file3.cpp …
-
-
Naturally, if you want to change the name of a source file you can
-tell Boost.Build about it by editing the name in Jamroot.
-
-
-
Change the Name of your Extension Module
-
The name of the extension module is determined by two things:
-
-
the name in Jamroot immediately following python-extension, and
-
the name passed to BOOST_PYTHON_MODULE in extending.cpp.
-
-
To change the name of the extension module from extending to
-hello, you'd edit Jamroot, changing
Since Boost.Python is a separately-compiled (as opposed to
-header-only) library, its user relies on the services of a
-Boost.Python library binary.
-
If you need a regular installation of the Boost.Python library
-binaries on your system, the Boost Getting Started Guide will
-walk you through the steps of creating one. If building binaries
-from source, you might want to supply the --with-python
-argument to bjam (or the --with-libraries=python argument
-to configure), so only the Boost.Python binary will be built,
-rather than all the Boost binaries.
As described in the Boost.Build reference manual, a file called
-user-config.jam in your home directory6 is used to
-specify the tools and libraries available to the build system. You
-may need to create or edit user-config.jam to tell Boost.Build
-how to invoke Python, #include its headers, and link with its
-libraries.
-
-
Users of Unix-Variant OSes
-
If you are using a unix-variant OS and you ran Boost's
-configure script, it may have generated a
-user-config.jam for you.4 If your configure/make sequence was successful and Boost.Python binaries
-were built, your user-config.jam file is probably already
-correct.
-
-
If you have one fairly “standard” python installation for your
-platform, you might not need to do anything special to describe it. If
-you haven't configured python in user-config.jam (and you don't
-specify --without-python on the Boost.Build command line),
-Boost.Build will automatically execute the equivalent of
-
-import toolset : using ;
-using python ;
-
-
which automatically looks for Python in the most likely places.
-However, that only happens when using the Boost.Python project file
-(e.g. when referred to by another project as in the quickstart
-method). If instead you are linking against separately-compiled
-Boost.Python binaries, you should set up a user-config.jam file
-with at least the minimal incantation above.
If you have several versions of Python installed, or Python is
-installed in an unusual way, you may want to supply any or all of
-the following optional parameters to usingpython.
-
-
version
-
the version of Python to use. Should be in Major.Minor
-format, for example, 2.3. Do not include the subminor
-version (i.e. not2.5.1). If you have multiple Python
-versions installed, the version will usually be the only
-configuration argument required.
-
cmd-or-prefix
-
preferably, a command that invokes a Python interpreter.
-Alternatively, the installation prefix for Python libraries and
-header files. Only use the alternative formulation if there is
-no appropriate Python executable available.
-
includes
-
the #include paths for Python headers. Normally the correct
-path(s) will be automatically deduced from version and/or
-cmd-or-prefix.
-
libraries
-
the path to Python library binaries. On MacOS/Darwin,
-you can also pass the path of the Python framework. Normally the
-correct path(s) will be automatically deduced from version
-and/or cmd-or-prefix.
-
condition
-
if specified, should be a set of Boost.Build
-properties that are matched against the build configuration when
-Boost.Build selects a Python configuration to use. See examples
-below for details.
-
extension-suffix
-
A string to append to the name of extension
-modules before the true filename extension. You almost certainly
-don't need to use this. Usually this suffix is only used when
-targeting a Windows debug build of Python, and will be set
-automatically for you based on the value of the
-<python-debugging> feature. However, at least one Linux
-distribution (Ubuntu Feisty Fawn) has a specially configured
-python-dbg package that claims to use such a suffix.
Note that in the examples below, case and especially whitespace are
-significant.
-
-
If you have both python 2.5 and python 2.4 installed,
-user-config.jam might contain:
-
-using python : 2.5 ; # Make both versions of Python available
-
-using python : 2.4 ; # To build with python 2.4, add python=2.4
- # to your command line.
-
-
The first version configured (2.5) becomes the default. To build
-against python 2.4, add python=2.4 to the bjam command line.
-
-
If you have python installed in an unusual location, you might
-supply the path to the interpreter in the cmd-or-prefix
-parameter:
You can set up your user-config.jam so a bjam built under Windows
-can build/test both Windows and Cygwin python extensions. Just pass
-<target-os>cygwin in the condition parameter
-for the cygwin python installation:
when you put target-os=cygwin in your build request, it should build
-with the cygwin version of python:5
-
-
bjam target-os=cygwin toolset=gcc
-
-
This is supposed to work the other way, too (targeting windows
-python with a Cygwin bjam) but it seems as though the support in
-Boost.Build's toolsets for building that way is broken at the
-time of this writing.
If—instead of letting Boost.Build construct and link with the right
-libraries automatically—you choose to use a pre-built Boost.Python
-library, you'll need to think about which one to link with. The
-Boost.Python binary comes in both static and dynamic flavors. Take
-care to choose the right flavor for your application.2
The dynamic library is the safest and most-versatile choice:
-
-
A single copy of the library code is used by all extension
-modules built with a given toolset.3
-
The library contains a type conversion registry. Because one
-registry is shared among all extension modules, instances of a
-class exposed to Python in one dynamically-loaded extension
-module can be passed to functions exposed in another such module.
It might be appropriate to use the static Boost.Python library in
-any of the following cases:
-
-
You are extending python and the types exposed in your
-dynamically-loaded extension module don't need to be used by any
-other Boost.Python extension modules, and you don't care if the
-core library code is duplicated among them.
-
You are embedding python in your application and either:
-
You are targeting a Unix variant OS other than MacOS or AIX,
-where the dynamically-loaded extension modules can “see” the
-Boost.Python library symbols that are part of the executable.
-
Or, you have statically linked some Boost.Python extension
-modules into your application and you don't care if any
-dynamically-loaded Boost.Python extension modules are able to
-use the types exposed by your statically-linked extension
-modules (and vice-versa).
If you should ever have occasion to #include"python.h"
-directly in a translation unit of a program using Boost.Python,
-use #include"boost/python/detail/wrap_python.hpp" instead.
-It handles several issues necessary for use with Boost.Python,
-one of which is mentioned in the next section.
-
Be sure not to #include any system headers before
-wrap_python.hpp. This restriction is actually imposed by
-Python, or more properly, by Python's interaction with your
-operating system. See
-http://docs.python.org/ext/simpleExample.html for details.
Python can be built in a special “python debugging” configuration
-that adds extra checks and instrumentation that can be very useful
-for developers of extension modules. The data structures used by
-the debugging configuration contain additional members, so a
-Python executable built with python debugging enabled cannot be
-used with an extension module or library compiled without it, and
-vice-versa.
-
Since pre-built “python debugging” versions of the Python
-executable and libraries are not supplied with most distributions
-of Python,7 and we didn't want to force our users
-to build them, Boost.Build does not automatically enable python
-debugging in its debug build variant (which is the default).
-Instead there is a special build property called
-python-debugging that, when used as a build property, will
-define the right preprocessor symbols and select the right
-libraries to link with.
-
On unix-variant platforms, the debugging versions of Python's data
-structures will only be used if the symbol Py_DEBUG is defined.
-On many windows compilers, when extension modules are built with
-the preprocessor symbol _DEBUG, Python defaults to force
-linking with a special debugging version of the Python DLL. Since
-that symbol is very commonly used even when Python is not present,
-Boost.Python temporarily undefines _DEBUG when Python.h
-is #included from boost/python/detail/wrap_python.hpp - unless
-BOOST_DEBUG_PYTHON is defined. The upshot is that if you want
-“python debugging”and you aren't using Boost.Build, you should make
-sure BOOST_DEBUG_PYTHON is defined, or python debugging will be
-suppressed.
If you are using a version of Python prior to 2.4.1 with a MinGW
-prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
-create a MinGW-compatible version of the Python library; the one
-shipped with Python will only work with a Microsoft-compatible
-linker. Follow the instructions in the “Non-Microsoft” section of
-the “Building Extensions: Tips And Tricks” chapter in Installing
-Python Modules to create libpythonXX.a, where XX
-corresponds to the major and minor version numbers of your Python
-installation.
Note that although we tested earlier versions of
-Boost.Python with Python 2.2, and we don't think we've done
-anything to break compatibility, this release of Boost.Python
-may not have been tested with versions of Python earlier than
-2.4, so we're not 100% sure that python 2.2 and 2.3 are
-supported.
Because of the way most *nix platforms
-share symbols among dynamically-loaded objects, I'm not certain
-that extension modules built with different compiler toolsets
-will always use different copies of the Boost.Python library
-when loaded into the same Python instance. Not using different
-libraries could be a good thing if the compilers have compatible
-ABIs, because extension modules built with the two libraries
-would be interoperable. Otherwise, it could spell disaster,
-since an extension module and the Boost.Python library would
-have different ideas of such things as class layout. I would
-appreciate someone doing the experiment to find out what
-happens.
Note that the <target-os>cygwin feature is
-different from the <flavor>cygwin subfeature of the gcc
-toolset, and you might need handle both explicitly if you also
-have a MinGW GCC installed.
On Unix and similar platforms, a debugging
-python and associated libraries are built by adding
---with-pydebug when configuring the Python build. On
-Windows, the debugging version of Python is generated by
-the "Win32 Debug" target of the Visual Studio project in the
-PCBuild subdirectory of a full Python source code distribution.
-
- Welcome to version 2 of Boost.Python, a C++ library which enables
- seamless interoperability between C++ and the Python programming language. The new version
- has been rewritten from the ground up, with a more convenient and
- flexible interface, and many new capabilities, including support for:
-
-
This new feature increases the size of the modules by about 14%.
- If this is not acceptable it can be turned off by defining the macro
- BOOST_PYTHON_NO_PY_SIGNATURES. Modules compiled with and without the macro
- defined are compatible.
-
-
If BOOST_PYTHON_NO_PY_SIGNATURES is undefined, this version defines the
- macro BOOST_PYTHON_SUPPORTS_PY_SIGNATURES. This allows writing code that will compile
- with older version of Boost.Python (see here).
-
-
By defining BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE, and at a cost
- of another 14% size increase, proper pythonic type is generated for the "self"
- parameter of the __init__ methods.
-
Support for converting void* to/from python,
- with opaque_pointer_converter
- as the return value policy. Thanks to Niall Douglas for the
- initial patch.
-
-
-
-
19 October 2005 - 1.33.1 release
-
-
-
-
wrapper<T> can now be used as expected with a
- held type of some-smart-pointer<T>
-
-
The build now assumes Python 2.4 by default, rather than 2.2
-
-
Support Python that's built without Unicode support
-
-
Support for wrapping classes with overloaded address-of
- (&) operators
-
-
-
-
14 August 2005 - 1.33 release
-
-
-
-
Support for docstrings on nonstatic properties.
-
-
We now export the client-provided docstrings for
- init<optional<> > and
- XXX_FUNCTION_OVERLOADS() for only the last
- overload.
-
-
Fixed some support for Embedded VC++ 4
-
-
Better support for rvalue from-python conversions of shared_ptr:
- always return a pointer that holds the owning python object *unless*
- the python object contains a NULL shared_ptr holder of the right
- type.
-
-
Support for exposing vector<T*> with the
- indexing suite.
-
-
Support for GCC-3.3 on MacOS.
-
-
updated visual studio project build file to include two new files
- (slice.cpp and wrapper.cpp)
-
-
Added search feature to the index page.
-
-
Numerous fixes to the tutorial
-
-
Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG
- 2.45
-
-
-
-
11 March 2005
-
-
-
-
Added a hack that will fool PyDoc into working with Boost.Python,
- thanks to Nick Rasmussen
Support for upcoming GCC symbol export control features have been
- folded in, thanks to Niall Douglas.
-
-
Improved support for std::auto_ptr-like types.
-
-
The Visual C++ bug that makes top-level cv-qualification
- of function parameter types part of the function type has been worked
- around.
-
-
Components used by other libraries have been moved out of
- python/detail and into boost/detail to
- improve dependency relationships.
-
-
Miscellaneous bug fixes and compiler workarounds.
-
-
-
-
8 Sept 2004
-
-
Support for Python's Bool type, thanks to Daniel Holth.
-
-
11 Sept 2003
-
-
-
-
Changed the response to multiple to-python converters being
- registered for the same type from a hard error into warning;
- Boost.Python now reports the offending type in the message.
constructors which take a range of characters, allowing strings
- containing nul ('\0') characters.
-
-
8 Sept 2003
-
-
Added the ability to create methods from function objects (with an
- operator()); see the make_function docs for
- more info.
-
-
10 August 2003
-
-
Added the new properties unit tests contributed by
- Roman Yakovenko and
- documented add_static_property at his urging.
-
-
1 August 2003
-
-
- Added the new arg class contributed by Nikolay Mladenov which supplies the
- ability to wrap functions that can be called with ommitted arguments in
- the middle:
-
-void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
-
-BOOST_PYTHON_MODULE(test)
-{
- def("f", f
- , (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
-}
-
-
And in Python:
-
->>> import test
->>> f(0, z = "bar")
->>> f(z = "bar", y = 0.0)
-
Thanks, Nikolay!
-
-
-
22 July 2003
-
-
Killed the dreaded "bad argument type for builtin operation" error.
- Argument errors now show the actual and expected argument types!
Finished improved support for boost::shared_ptr. Now any
- wrapped object of C++ class X can be converted automatically
- to shared_ptr<X>, regardless of how it was wrapped.
- The shared_ptr will manage the lifetime of the Python object
- which supplied the X, rather than just the X
- object itself, and when such a shared_ptr is converted back
- to Python, the original Python object will be returned.
-
-
19 January 2003
-
-
Integrated staticmethod support from Nikolay Mladenov. Thanks, Nikolay!
-
-
29 December 2002
-
-
Added Visual Studio project file and instructions from Brett Calcott.
- Thanks, Brett!
-
-
20 December 2002
-
-
Added automatic downcasting for pointers, references, and smart
- pointers to polymorphic class types upon conversion to python
-
-
18 December 2002
-
-
Optimized from_python conversions for wrapped classes by putting the
- conversion logic in the shared library instead of registering separate
- converters for each class in each extension module
-
-
19 November 2002
-
-
Removed the need for users to cast base class member function
- pointers when used as arguments to add_property
-
-
13 December 2002
-
-
Allow exporting of enum_ values into enclosing
- scope.
- Fixed unsigned integer conversions to deal correctly with numbers that
- are out-of-range of signed long.
-
-
14 November 2002
-
-
Auto-detection of class data members wrapped with make_getter
-
-
13 November 2002
-
-
Full Support for std::auto_ptr<> added.
-
-
October 2002
-
-
Ongoing updates and improvements to tutorial documentation
This is a partial list of projects using Boost.Python. If you are using
- Boost.Python as your Python/C++ binding solution, we'd be proud to list
- your project on this page. Just post a short description of your project
- and how Boost.Python helps you get the job done, and we'll add it to this
- page .
Neuralab is a data analysis environment specifically tailored for
- neural data from Neuralynx
- acquisition systems. Neuralab combines presentation quality graphics, a
- numerical analysis library, and the Python scripting engine in a single
- application. With Neuralab, Neuralynx users can perform common analysis
- tasks with just a few mouse clicks. More advanced users can create custom
- Python scripts, which can optionally be assigned to menus and mouse
- clicks.
- Fortress Investment Group has contracted Boost Consulting to develop core
- internal financial analysis tools in C++ and to prepare Python bindings
- for them using Boost.Python.
-
-
Tom Barket of Fortress writes:
-
-
- We have a large C++ analytical library specialized for research in
- finance and economics, built for speed and mission critical
- stability. Yet Python offers us the flexibility to test out new ideas
- quickly and increase the productivity of our time versus working in
- C++. There are several key features which make Python stand out. Its
- elegance, stability, and breadth of resources on the web are all
- valuable, but the most important is its extensibility, due to its
- open source transparency. Boost.Python makes Python extensibility
- extremely simple and straightforward, yet preserves a great deal of
- power and control.
-
KDE Interactive Geometry is a high-school level educational tool,
- built for the KDE desktop. It is a nice tool to let students work with
- geometrical constructions. It is meant to be the most intuitive, yet
- featureful application of its kind.
-
-
Versions after 0.6.x (will) support objects built by the user
- himself in the Python language. The exporting of the relevant internal
- API's were done using Boost.Python, which made the process very
- easy.
- The OpenWBEM project is an effort to develop an open-source
- implementation of Web Based Enterprise Management suitable for
- commercial and non-commercial application
-
-
- I'm using Boost.Python to wrap the client API of OpenWBEM.This will
- make it easier to do rapid prototyping, testing, and scripting when
- developing management solutions that use WBEM.
-
- Boost.Python is used in an automated process to generate python
- bindings to our api which is exposed though multiple backends and
- frontends. This allows us to write quick tests and bespoke scripts to
- perform one off tasks without having to go through the full
- compilation cycle.
-
- “The fourth game in the PC strategy series that has sold over five
- million copies, Sid Meier's Civilization IV is a bold step forward for
- the franchise, with spectacular new 3D graphics and all-new single and
- multiplayer content. Civilization IV will also set a new standard for
- user-modification, allowing gamers to create their own add-ons using
- Python and XML.
-
-
Boost.Python is used as the interface layer between the C++ game code
- and Python. Python is used for many purposes in the game, including map
- generation, interface screens, game events, tools, tutorials, etc. Most
- high-level game operations have been exposed to Python in order to give
- modders the power they need to customize the game.
- Vega Strike is the 3D
- Space Simulator that allows you to trade and bounty hunt in a vast
- universe. Players face dangers, decisions, piracy, and aliens.
-
-
Vega Strike has
- decided to base its scripting on python, using boost as the layer
- between the class hierarchy in python and the class hierarchy in C++.
- The result is a very flexible scripting system that treats units as
- native python classes when designing missions or writing AI's.
-
-
A large economic and planetary simulation is currently being run in
- the background in python and the results are returned back into C++ in
- the form of various factions' spaceships appearing near worlds that
- they are simulated to be near in python if the player is in the general
- neighborhood.
- HippoDraw is a data analysis environment consisting of a canvas upon
- which graphs such as histograms, scattter plots, etc, are prsented. It
- has a highly interactive GUI interface, but some things you need to do
- with scripts. HippoDraw can be run as Python extension module so that
- all the manipulation can be done from either Python or the GUI.
-
-
Before the web page came online, Paul F. Kunz wrote:
-
-
- Don't have a web page for the project, but the organization's is
- http://www.slac.stanford.edu (the
- first web server site in America, I installed it).
-
Which was just too cool a piece of trivia to omit.
-
-
- IPLT is an image processing library and toolbox for the structural
- biology electron microscopy community. I would call it a
- budding/evolving project, since it is currently not in production
- stage, but rather under heavy development. Python is used as the main
- scripting/interaction level, but also for rapid prototyping, since
- the underlying C++ class library is pretty much fully exposed via
- boost.python (at least the high-level interface). The combined power
- of C++ and Python for this project turned out to be just awesome.
-
- VPython is an extension for Python that makes it easy to create
- navigable 3D animations, which are generated as a side effect of
- computational code. VPython is used in education for various
- purposes, including teaching physics and programming, but it has also
- been used by research scientists to visualize systems or data in 3D.
-
- Computational Crystallography is concerned with the derivation of
- atomic models of crystal structures, given experimental X-ray
- diffraction data. The cctbx is an open-source library of fundamental
- algorithms for crystallographic computations. The core algorithms are
- implemented in C++ and accessed through higher-level Python interfaces.
-
-
The cctbx grew together with Boost.Python and is designed from the
- ground up as a hybrid Python/C++ system. With one minor exception,
- run-time polymorphism is completely handled by Python. C++ compile-time
- polymorphism is used to implement performance critical algorithms. The
- Python and C++ layers are seamlessly integrated using Boost.Python.
-
-
The SourceForge cctbx project is organized in modules to facilitate
- use in non-crystallographic applications. The scitbx module implements
- a general purpose array family for scientific applications and pure C++
- ports of FFTPACK and the L-BFGS quasi-Newton minimizer.
- Gaudi is a framework for particle physics collision data processing
- applications developed in the context of the LHCb and ATLAS experiments
- at CERN.
-
-
- We are using Boost.Python to provide scripting/interactive capability
- to our framework. We have a module called "GaudiPython" implemented
- using Boost.Python that allows the interaction with any framework
- service or algorithm from python. RootPython also uses Boost.Python
- to provide a generic "gateway" between the ROOT framework and python
-
-
Boost.Python is great. We managed very quickly to interface our
- framework to python, which is great language. We are trying to
- facilitate to our physicists (end-users) a rapid analysis application
- development environment based on python. For that, Boost.Python plays
- and essential role.
- ESSS (Engineering Simulation and Scientific Software) is a company that
- provides engineering solutions and acts in the brazilian and
- south-american market providing products and services related to
- Computational Fluid Dynamics and Image Analysis.
-
-
- Recently we moved our work from working exclusively with C++ to an
- hybrid-language approach, using Python and C++, with Boost.Python
- providing the layer between the two. The results are great so far!
-
-
-
Two projects have been developed so far with this technology:
-
-
Simba
- provides 3D visualization of geological formations gattered from the
- simulation of the evolution of oil systems, allowing the user to
- analyse various aspects of the simulation, like deformation, pressure
- and fluids, along the time of the simulation.
-
-
Aero aims to
- construct a CFD with brazilian technology, which involves various
- companies and universities. ESSS is responsible for various of the
- application modules, including GUI and post-processing of results.
The core of PolyBoRi is a C++ library, which provides
- high-level data types for Boolean polynomials and monomials,
- exponent vectors, as well as for the underlying polynomial
- rings and subsets of the powerset of the Boolean variables. As
- a unique approach, binary decision diagrams are used as
- internal storage type for polynomial structures. On top of
- this C++-library we provide a Python interface. This allows
- parsing of complex polynomial systems, as well as sophisticated
- and extendable strategies for Gröbner basis computation.
- Boost.Python has helped us to create this interface in a
- very clean way.
Pyrap is the python interface to the Radio-Astronomical Package
- casacore (casacore.googlecode.com). Astronomers love pyrap because
- it makes it easily possible to get their data (observed with
- radio-astronomical telescopes like LOFAR, ASKAP, and eVLA) in numpy
- arrays and do basic data inspection and manipulation using the many
- python packages that are available.
-
-
Boost.Python made it quite easily possible to create converters for
- the various data types, also for numpy arrays and individual elements
- of a numpy array. It's nice they work fully recursively. Mapping C++
- functions to Python was straightforward.
Fusion is a library that supports implementing protocols in C++ for
- use with Twisted, allowing control over memory allocation strategies,
- fast method calls internally, etc.. Fusion supports TCP, UDP and
- multicast, and is implemented using the Boost.Python python
- bindings.
- Jayacard aims at developing a secure portable open source operating
- system for contactless smart cards and a complete suite of high quality
- development tools to ease smart card OS and application development.
-
-
The core of the smart card reader management is written in C++ but
- all the development tools are written in the friendly Python language.
- Boost plays the fundamental role of binding the tools to our core smart
- card reader library.
-
-
diff --git a/doc/python.qbk b/doc/python.qbk
index 24417290..b3e7eceb 100644
--- a/doc/python.qbk
+++ b/doc/python.qbk
@@ -48,16 +48,17 @@ The development of these features was funded in part by grants to `Boost Consult
* _reference_
* [link configuration Configuration Information]
* [link glossary Glossary]
-* Support Resources
+* [link support Support Resources]
* [link faq Frequently Asked Questions (FAQs)]
[endsect]
[h2 Articles]
-[@bpl.html Building Hybrid Systems With Boost Python], by Dave Abrahams and Ralf W. Grosse-Kunstleve ([@bpl.pdf PDF])
+[@article.html Building Hybrid Systems With Boost Python], by Dave Abrahams and Ralf W. Grosse-Kunstleve
[include building.qbk]
[include configuration.qbk]
+[include support.qbk]
[include faq.qbk]
[include glossary.qbk]
\ No newline at end of file
diff --git a/doc/support.html b/doc/support.html
deleted file mode 100644
index 31985634..00000000
--- a/doc/support.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Boost.Python - Support Resources
-
-
-
-
This is a list of available resources for support with Boost.Python
- problems and feature requests. Please try to resist emailing the
- Boost.Python developers directly for support. Use the following
- resources instead; the developers are listening!
-
-
-
-
Boost
- Consulting - Commercial support, development, training, and
- distribution for all the Boost libraries, from the people who brought
- you Boost.Python.
-
-
-
The Python
- C++-sig mailing list is a forum for discussing Python/C++
- interoperability, and Boost.Python in particular. Post your
- Boost.Python questions here.
-
-
-
The Boost.Python Wiki
- Pages established by Mike Rovner as part of the PythonInfo Wiki serves as
- a forum to gather peoples' experience and as a cookbook.
-
-
-
-
diff --git a/doc/support.qbk b/doc/support.qbk
new file mode 100644
index 00000000..f075e3e9
--- /dev/null
+++ b/doc/support.qbk
@@ -0,0 +1,17 @@
+[chapter Support Resources
+ [quickbook 1.7]
+ [id support]
+]
+
+
+[h2 Synopsis]
+This is a list of available resources for support with Boost.Python problems and feature requests. Please try to resist emailing the Boost.Python developers directly for support. Use the following resources instead; the developers are listening!
+
+[h2 Support]
+* The _bp_list_ is a forum for discussing Python/C++ interoperability, and Boost.Python in particular. Post your Boost.Python questions here.
+* The _bb_list_ is a forum for discussing Boost's Build System.
+* The Boost.Python [@https://github.com/boostorg/python/issues Issue tracker]
+ [note In the past we used Trac, which still hosts a considerable number of [@https://svn.boost.org/trac/boost/query?status=!closed&component=python+USE+GITHUB open issues]. We hope to be able to either close them or migrate them to the new issue tracker.]
+* The Boost.Python [@https://github.com/boostorg/python/wiki Wiki]
+* Boost.Python [@https://github.com/boostorg/python Source repository]
+
diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk
index 3d3f6947..83c6b2b3 100644
--- a/doc/tutorial.qbk
+++ b/doc/tutorial.qbk
@@ -1,4 +1,5 @@
[article Boost.Python Tutorial
+ [quickbook 1.7]
[authors [de Guzman, Joel], [Abrahams, David]]
[copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams]
[category inter-language support]
@@ -15,11 +16,11 @@
[/ QuickBook Document version 0.9 ]
-[def __note__ [$images/note.png]]
-[def __alert__ [$images/alert.png]]
-[def __tip__ [$images/tip.png]]
-[def :-) [$images/smiley.png]]
-[def __jam__ [$images/jam.png]]
+[def __note__ [$../images/note.png]]
+[def __alert__ [$../images/alert.png]]
+[def __tip__ [$../images/tip.png]]
+[def :-) [$../images/smiley.png]]
+[def __jam__ [$../images/jam.png]]
[section QuickStart]
@@ -1074,7 +1075,7 @@ bidirectional mapping between C++ and Python while maintaining the Python
feel. Boost.Python C++ [^object]s are as close as possible to Python. This
should minimize the learning curve significantly.
-[$images/python.png]
+[$../images/python.png]
[section Basic Interface]
diff --git a/doc/tutorial/doc/Jamfile.v2 b/doc/tutorial/doc/Jamfile.v2
deleted file mode 100644
index ba888263..00000000
--- a/doc/tutorial/doc/Jamfile.v2
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright Joel de Guzman 2006. Distributed under the Boost
-# Software License, Version 1.0. (See accompanying
-# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-project boost/libs/python/doc/tutorial/doc ;
-
-import boostbook : boostbook ;
-using quickbook ;
-
-path-constant images : html ;
-
-boostbook tutorial
- :
- tutorial.qbk
- :
- boost.root=../../../../../..
- pdf:img.src.path=$(images)/
- pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/python/doc/tutorial/doc/html
- ;
diff --git a/doc/tutorial/doc/html/images/alert.png b/doc/tutorial/doc/html/images/alert.png
deleted file mode 100755
index b4645bc7..00000000
Binary files a/doc/tutorial/doc/html/images/alert.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/home.png b/doc/tutorial/doc/html/images/home.png
deleted file mode 100755
index 5584aacb..00000000
Binary files a/doc/tutorial/doc/html/images/home.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/jam.png b/doc/tutorial/doc/html/images/jam.png
deleted file mode 100644
index 224ed791..00000000
Binary files a/doc/tutorial/doc/html/images/jam.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/next.png b/doc/tutorial/doc/html/images/next.png
deleted file mode 100755
index 59800b4e..00000000
Binary files a/doc/tutorial/doc/html/images/next.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/note.png b/doc/tutorial/doc/html/images/note.png
deleted file mode 100755
index 3ed047ca..00000000
Binary files a/doc/tutorial/doc/html/images/note.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/prev.png b/doc/tutorial/doc/html/images/prev.png
deleted file mode 100755
index d88a40f9..00000000
Binary files a/doc/tutorial/doc/html/images/prev.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/smiley.png b/doc/tutorial/doc/html/images/smiley.png
deleted file mode 100644
index 30a77f71..00000000
Binary files a/doc/tutorial/doc/html/images/smiley.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/tip.png b/doc/tutorial/doc/html/images/tip.png
deleted file mode 100755
index 9f596b0b..00000000
Binary files a/doc/tutorial/doc/html/images/tip.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/images/up.png b/doc/tutorial/doc/html/images/up.png
deleted file mode 100755
index 17d9c3ec..00000000
Binary files a/doc/tutorial/doc/html/images/up.png and /dev/null differ
diff --git a/doc/tutorial/doc/html/index.html b/doc/tutorial/doc/html/index.html
deleted file mode 100644
index c324f065..00000000
--- a/doc/tutorial/doc/html/index.html
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-Chapter 1. python 2.0
-
-
-
-
-
-
-
- The Boost Python Library is a framework for interfacing Python and C++. It
- allows you to quickly and seamlessly expose C++ classes functions and objects
- to Python, and vice-versa, using no special tools -- just your C++ compiler.
- It is designed to wrap C++ interfaces non-intrusively, so that you should not
- have to change the C++ code at all in order to wrap it, making Boost.Python
- ideal for exposing 3rd-party libraries to Python. The library's use of advanced
- metaprogramming techniques simplifies its syntax for users, so that wrapping
- code takes on the look of a kind of declarative interface definition language
- (IDL).
-
-
-
- Hello World
-
-
- Following C/C++ tradition, let's start with the "hello, world". A
- C++ Function:
-
-
charconst*greet()
-{
- return"hello, world";
-}
-
-
- can be exposed to Python by writing a Boost.Python wrapper:
-
- By now you should know how to use Boost.Python to call your C++ code from Python.
- However, sometimes you may need to do the reverse: call Python code from the
- C++-side. This requires you to embed the Python interpreter
- into your C++ program.
-
-
- Currently, Boost.Python does not directly support everything you'll need when
- embedding. Therefore you'll need to use the Python/C
- API to fill in the gaps. However, Boost.Python already makes embedding
- a lot easier and, in a future version, it may become unnecessary to touch the
- Python/C API at all. So stay tuned...
-
-
-
- Building embedded programs
-
-
- To be able to embed python into your programs, you have to link to both Boost.Python's
- as well as Python's own runtime library.
-
-
- Boost.Python's library comes in two variants. Both are located in Boost's
- /libs/python/build/bin-stage subdirectory. On Windows, the
- variants are called boost_python.lib (for release builds)
- and boost_python_debug.lib (for debugging). If you can't
- find the libraries, you probably haven't built Boost.Python yet. See Building and Testing on how to do this.
-
-
- Python's library can be found in the /libs subdirectory
- of your Python directory. On Windows it is called pythonXY.lib where X.Y is
- your major Python version number.
-
-
- Additionally, Python's /include subdirectory has to be added
- to your include path.
-
-
- In a Jamfile, all the above boils down to:
-
-
projectroot c:\projects\embedded_program ; # location of the program
-
-# bring in the rules for python
-SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
-include python.jam ;
-
-exe embedded_program # name of the executable
- : #sources
- embedded_program.cpp
- : # requirements
- <find-library>boost_python <library-path>c:\boost\libs\python
- $(PYTHON_PROPERTIES)
- <library-path>$(PYTHON_LIB_PATH)
- <find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
-
-
-
- Getting started
-
-
- Being able to build is nice, but there is nothing to build yet. Embedding the
- Python interpreter into one of your C++ programs requires these 4 steps:
-
-
-
- #include <boost/python.hpp>
-
-
- Call Py_Initialize()
- to start the interpreter and create the __main__ module.
-
-
- Call other Python C API routines to use the interpreter.
-
-
-
-
-
-
Note
-
-
- Note that at this time you must not call Py_Finalize()
- to stop the interpreter. This may be fixed in a future version of boost.python.
-
-
-
- (Of course, there can be other C++ code between all of these steps.)
-
-
- Now that we can embed the interpreter in
- our programs, lets see how to put it to use...
-
-
-
-Using the interpreter
-
- As you probably already know, objects in Python are reference-counted. Naturally,
- the PyObjects of the Python C API are also reference-counted.
- There is a difference however. While the reference-counting is fully automatic
- in Python, the Python C API requires you to do it by
- hand. This is messy and especially hard to get right in the presence
- of C++ exceptions. Fortunately Boost.Python provides the handle
- and object class templates to
- automate the process.
-
-
-
- Running Python code
-
-
- Boost.python provides three related functions to run Python code from C++.
-
- eval evaluates the given expression and returns the resulting value. exec
- executes the given code (typically a set of statements) returning the result,
- and exec_file executes the code contained in the given file.
-
-
- The globals and locals parameters are
- Python dictionaries containing the globals and locals of the context in which
- to run the code. For most intents and purposes you can use the namespace
- dictionary of the __main__ module for both parameters.
-
-
- Boost.python provides a function to import a module:
-
-
objectimport(strname)
-
-
- import imports a python module (potentially loading it into the running process
- first), and returns it.
-
-
- Let's import the __main__ module and run some Python code
- in its namespace:
-
- This should create a file called 'hello.txt' in the current directory containing
- a phrase that is well-known in programming circles.
-
-
-
- Manipulating Python objects
-
-
- Often we'd like to have a class to manipulate Python objects. But we have
- already seen such a class above, and in the previous
- section: the aptly named object class and its
- derivatives. We've already seen that they can be constructed from a handle.
- The following examples should further illustrate this fact:
-
- Here we create a dictionary object for the __main__ module's
- namespace. Then we assign 5 squared to the result variable and read this
- variable from the dictionary. Another way to achieve the same result is to
- use eval instead, which returns the result directly:
-
- If an exception occurs in the evaluation of the python expression, error_already_set
- is thrown:
-
-
try
-{
- objectresult=eval("5/0");
- // execution will never get here:
- intfive_divided_by_zero=extract<int>(result);
-}
-catch(error_already_setconst&)
-{
- // handle the exception in some way
-}
-
-
- The error_already_set exception class doesn't carry any
- information in itself. To find out more about the Python exception that occurred,
- you need to use the exception
- handling functions of the Python C API in your catch-statement. This
- can be as simple as calling PyErr_Print()
- to print the exception's traceback to the console, or comparing the type
- of the exception with those of the standard
- exceptions:
-
- All C++ exceptions must be caught at the boundary with Python code. This boundary
- is the point where C++ meets Python. Boost.Python provides a default exception
- handler that translates selected standard exceptions, then gives up:
-
-
raiseRuntimeError,'unidentifiable C++ Exception'
-
-
- Users may provide custom translation. Here's an example:
-
- Here, we wrote a C++ class wrapper that exposes the member functions greet
- and set. Now, after building our module as a shared library,
- we may use our class World in Python. Here's a sample Python
- session:
-
- Our previous example didn't have any explicit constructors. Since World
- is declared as a plain struct, it has an implicit default constructor. Boost.Python
- exposes the default constructor by default, which is why we were able to
- write
-
-
>>>planet=hello.World()
-
-
- We may wish to wrap a class with a non-default constructor. Let us build
- on our previous example:
-
- This time World has no default constructor; our previous
- wrapping code would fail to compile when the library tried to expose it.
- We have to tell class_<World> about the constructor
- we want to expose instead.
-
- init<std::string>() exposes the constructor taking
- in a std::string (in Python, constructors are spelled
- ""__init__"").
-
-
- We can expose additional constructors by passing more init<...>s
- to the def() member function. Say for example we have
- another World constructor taking in two doubles:
-
- On the other hand, if we do not wish to expose any constructors at all, we
- may use no_init instead:
-
-
class_<Abstract>("Abstract",no_init)
-
-
- This actually adds an __init__ method which always raises
- a Python RuntimeError exception.
-
-
-
-
-Class Data Members
-
- Data members may also be exposed to Python so that they can be accessed as
- attributes of the corresponding Python class. Each data member that we wish
- to be exposed may be regarded as read-only
- or read-write. Consider this class Var:
-
- Note that name is exposed as read-only
- while value is exposed as read-write.
-
-
>>>x.name='e'# can't change name
-Traceback(mostrecentcalllast):
- File"<stdin>",line1,in?
-AttributeError:can'tsetattribute
-
-
-
-
-Class Properties
-
- In C++, classes with public data members are usually frowned upon. Well designed
- classes that take advantage of encapsulation hide the class' data members.
- The only way to access the class' data is through access (getter/setter)
- functions. Access functions expose class properties. Here's an example:
-
- However, in Python attribute access is fine; it doesn't neccessarily break
- encapsulation to let users handle attributes directly, because the attributes
- can just be a different syntax for a method call. Wrapping our Num
- class using Boost.Python:
-
- Take note that the class property rovalue is exposed as
- read-only since the rovalue
- setter member function is not passed in:
-
-
.add_property("rovalue",&Num::get)
-
-
-
-
-Inheritance
-
- In the previous examples, we dealt with classes that are not polymorphic.
- This is not often the case. Much of the time, we will be wrapping polymorphic
- classes and class hierarchies related by inheritance. We will often have
- to write Boost.Python wrappers for classes that are derived from abstract
- base classes.
-
- Derived automatically inherits all of Base's Python methods (wrapped
- C++ member functions)
-
-
- If Base is polymorphic, Derived
- objects which have been passed to Python via a pointer or reference to
- Base can be passed where a pointer or reference to
- Derived is expected.
-
-
-
- Now, we will expose the C++ free functions b and d
- and factory:
-
- Note that free function factory is being used to generate
- new instances of class Derived. In such cases, we use
- return_value_policy<manage_new_object> to instruct
- Python to adopt the pointer to Base and hold the instance
- in a new Python Base object until the the Python object
- is destroyed. We will see more of Boost.Python call
- policies later.
-
-
// Tell Python to take ownership of factory's result
-def("factory",factory,
- return_value_policy<manage_new_object>());
-
-
-
-
-Class Virtual Functions
-
- In this section, we will learn how to make functions behave polymorphically
- through virtual functions. Continuing our example, let us add a virtual function
- to our Base class:
-
- One of the goals of Boost.Python is to be minimally intrusive on an existing
- C++ design. In principle, it should be possible to expose the interface for
- a 3rd party library without changing it. It is not ideal to add anything
- to our class Base. Yet, when
- you have a virtual function that's going to be overridden in Python and called
- polymorphically from C++, we'll need to
- add some scaffoldings to make things work properly. What we'll do is write
- a class wrapper that derives from Base
- that will unintrusively hook into the virtual functions so that a Python
- override may be called:
-
- Notice too that in addition to inheriting from Base,
- we also multiply- inherited wrapper<Base> (See Wrapper).
- The wrapper template makes
- the job of wrapping classes that are meant to overridden in Python, easier.
-
-
-
-
- MSVC6/7 Workaround
-
-
- If you are using Microsoft Visual C++ 6 or 7, you have to write f as:
-
- pure_virtual signals Boost.Python
- that the function f is a
- pure virtual function.
-
-
-
-
-
Note
-
-
-
- member function and methods
-
-
- Python, like many object oriented languages uses the term methods.
- Methods correspond roughly to C++'s member functions
-
-
-
-
-
-
-Virtual Functions with Default Implementations
-
- We've seen in the previous section how classes with pure virtual functions
- are wrapped using Boost.Python's class
- wrapper facilities. If we wish to wrap non-pure-virtual
- functions instead, the mechanism is a bit different.
-
-
- Recall that in the previous
- section, we wrapped a class with a pure virtual function that we then
- implemented in C++, or Python classes derived from it. Our base class:
-
-
structBase
-{
- virtualintf()=0;
-};
-
-
- had a pure virtual function f. If, however, its member
- function f was not declared as pure virtual:
-
- Take note that we expose both &Base::f and &BaseWrap::default_f. Boost.Python needs to keep track
- of 1) the dispatch function f and 2) the forwarding function
- to its default implementation default_f. There's a special
- def function for this purpose.
-
- C is well known for the abundance of operators. C++ extends this to the extremes
- by allowing operator overloading. Boost.Python takes advantage of this and
- makes it easy to wrap C++ operator-powered classes.
-
-
- Consider a file position class FilePos and a set of operators
- that take on FilePos instances:
-
- The code snippet above is very clear and needs almost no explanation at all.
- It is virtually the same as the operators' signatures. Just take note that
- self refers to FilePos object. Also, not every class
- T that you might need to interact with in an operator
- expression is (cheaply) default-constructible. You can use other<T>()
- in place of an actual T instance when writing "self
- expressions".
-
-
-
- Special Methods
-
-
- Python has a few more Special Methods. Boost.Python
- supports all of the standard special method names supported by real Python
- class instances. A similar set of intuitive interfaces can also be used to
- wrap C++ functions that correspond to these Python special functions.
- Example:
-
- What is the business of operator<<? Well, the method str requires the operator<< to do its work (i.e. operator<<
- is used by the method defined by def(str(self)).
-
- In this chapter, we'll look at Boost.Python powered functions in closer detail.
- We will see some facilities to make exposing C++ functions to Python safe from
- potential pifalls such as dangling pointers and references. We will also see
- facilities that will make it even easier for us to expose C++ functions that
- take advantage of C++ features such as overloading and default arguments.
-
-
- Read on...
-
-
- But before you do, you might want to fire up Python 2.2 or later and type
- >>> import this.
-
-
>>> import this
-The Zen of Python, by Tim Peters
-Beautiful is better than ugly.
-Explicit is better than implicit.
-Simple is better than complex.
-Complex is better than complicated.
-Flat is better than nested.
-Sparse is better than dense.
-Readability counts.
-Special cases aren't special enough to break the rules.
-Although practicality beats purity.
-Errors should never pass silently.
-Unless explicitly silenced.
-In the face of ambiguity, refuse the temptation to guess.
-There should be one-- and preferably only one --obvious way to do it
-Although that way may not be obvious at first unless you're Dutch.
-Now is better than never.
-Although never is often better than right now.
-If the implementation is hard to explain, it's a bad idea.
-If the implementation is easy to explain, it may be a good idea.
-Namespaces are one honking great idea -- let's do more of those!
-
-
-
-Call Policies
-
- In C++, we often deal with arguments and return types such as pointers and
- references. Such primitive types are rather, ummmm, low level and they really
- don't tell us much. At the very least, we don't know the owner of the pointer
- or the referenced object. No wonder languages such as Java and Python never
- deal with such low level entities. In C++, it's usually considered a good
- practice to use smart pointers which exactly describe ownership semantics.
- Still, even good C++ interfaces use raw references and pointers sometimes,
- so Boost.Python must deal with them. To do this, it may need your help. Consider
- the following C++ function:
-
-
X&f(Y&y,Z*z);
-
-
- How should the library wrap this function? A naive approach builds a Python
- X object around result reference. This strategy might or might not work out.
- Here's an example where it didn't
-
- Well, what if f() was implemented as shown below:
-
-
X&f(Y&y,Z*z)
-{
- y.z=z;
- returny.x;
-}
-
-
- The problem is that the lifetime of result X& is tied to the lifetime
- of y, because the f() returns a reference to a member of the y object. This
- idiom is is not uncommon and perfectly acceptable in the context of C++.
- However, Python users should not be able to crash the system just by using
- our C++ interface. In this case deleting y will invalidate the reference
- to X. We have a dangling reference.
-
-
- Here's what's happening:
-
-
-
- f is called passing in a reference to y
- and a pointer to z
-
-
- A reference to y.x is returned
-
-
- y is deleted. x is a dangling reference
-
-
- x.some_method() is called
-
-
- BOOM!
-
-
-
- We could copy result into a new object:
-
-
>>>f(y,z).set(42)# Result disappears
->>>y.x.get()# No crash, but still bad
-3.14
-
-
- This is not really our intent of our C++ interface. We've broken our promise
- that the Python interface should reflect the C++ interface as closely as
- possible.
-
-
- Our problems do not end there. Suppose Y is implemented as follows:
-
- For reference, here's the implementation of f again:
-
-
X&f(Y&y,Z*z)
-{
- y.z=z;
- returny.x;
-}
-
-
- Here's what's happening:
-
-
-
- f is called passing in a reference to y
- and a pointer to z
-
-
- A pointer to z is held by y
-
-
- A reference to y.x is returned
-
-
- z is deleted. y.z is a dangling
- pointer
-
-
- y.z_value() is called
-
-
- z->value() is called
-
-
- BOOM!
-
-
-
-
- Call Policies
-
-
- Call Policies may be used in situations such as the example detailed above.
- In our example, return_internal_reference and with_custodian_and_ward
- are our friends:
-
- Informs Boost.Python that the first argument, in our case Y&
- y, is the owner of the returned reference: X&.
- The "1" simply specifies the first argument.
- In short: "return an internal reference X& owned
- by the 1st argument Y& y".
-
-
with_custodian_and_ward<1,2>
-
-
- Informs Boost.Python that the lifetime of the argument indicated by ward
- (i.e. the 2nd argument: Z* z) is dependent on the lifetime
- of the argument indicated by custodian (i.e. the 1st argument: Y&
- y).
-
-
- It is also important to note that we have defined two policies above. Two
- or more policies can be composed by chaining. Here's the general syntax:
-
- manage_new_object: Adopt a pointer
- and hold the instance
-
-
-
-
-
-
-
- Remember the Zen, Luke:
-
-
- "Explicit is better than implicit"
-
-
- "In the face of ambiguity, refuse the temptation to guess"
-
-
-
-
-
-Overloading
-
- The following illustrates a scheme for manually wrapping an overloaded member
- functions. Of course, the same technique can be applied to wrapping overloaded
- non-member functions.
-
- Boost.Python wraps (member) function pointers. Unfortunately, C++ function
- pointers carry no default argument info. Take a function f
- with default arguments:
-
-
intf(int,double=3.14,charconst*="hello");
-
-
- But the type of a pointer to the function f has no information
- about its default arguments:
-
- will automatically create the thin wrappers for us. This macro will create
- a class foo_overloads that can be passed on to def(...).
- The third and fourth macro argument are the minimum arguments and maximum
- arguments, respectively. In our foo function the minimum
- number of arguments is 1 and the maximum number of arguments is 4. The def(...)
- function will automatically add all the foo variants for us:
-
-
def("foo",foo,foo_overloads());
-
-
-
- BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
-
-
- Objects here, objects there, objects here there everywhere. More frequently
- than anything else, we need to expose member functions of our classes to
- Python. Then again, we have the same inconveniences as before when default
- arguments or overloads with a common sequence of initial arguments come into
- play. Another macro is provided to make this a breeze.
-
-
- Like BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
- may be used to automatically create the thin wrappers for wrapping member
- functions. Let's have an example:
-
- will generate a set of thin wrappers for george's wack_em
- member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
- the third and fourth macro argument). The thin wrappers are all enclosed
- in a class named george_overloads that can then be used
- as an argument to def(...):
-
- A similar facility is provided for class constructors, again, with default
- arguments or a sequence of overloads. Remember init<...>?
- For example, given a class X with a constructor:
-
- Notice the use of init<...> and optional<...>
- to signify the default (optional arguments).
-
-
-
-
-Auto-Overloading
-
- It was mentioned in passing in the previous section that BOOST_PYTHON_FUNCTION_OVERLOADS
- and BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS can also be
- used for overloaded functions and member functions with a common sequence
- of initial arguments. Here is an example:
-
- Notice though that we have a situation now where we have a minimum of zero
- (0) arguments and a maximum of 3 arguments.
-
-
-
- Manual Wrapping
-
-
- It is important to emphasize however that the overloaded
- functions must have a common sequence of initial arguments. Otherwise,
- our scheme above will not work. If this is not the case, we have to wrap
- our functions manually.
-
-
- Actually, we can mix and match manual wrapping of overloaded functions and
- automatic wrapping through BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
- and its sister, BOOST_PYTHON_FUNCTION_OVERLOADS. Following
- up on our example presented in the section on
- overloading, since the first 4 overload functins have a common sequence
- of initial arguments, we can use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
- to automatically wrap the first three of the defs and
- manually wrap just the last. Here's how we'll do this:
-
- Now the first thing you'd want to do is to build the Hello World module and
- try it for yourself in Python. In this section, we will outline the steps necessary
- to achieve that. We will use the build tool that comes bundled with every boost
- distribution: bjam.
-
-
-
-
-
Note
-
-
-
- Building without bjam
-
-
- Besides bjam, there are of course other ways to get your module built. What's
- written here should not be taken as "the one and only way". There
- are of course other build tools apart from bjam.
-
-
- Take note however that the preferred build tool for Boost.Python is bjam.
- There are so many ways to set up the build incorrectly. Experience shows
- that 90% of the "I can't build Boost.Python" problems come from
- people who had to use a different tool.
-
-
-
-
- We will skip over the details. Our objective will be to simply create the hello
- world module and run it in Python. For a complete reference to building Boost.Python,
- check out: building.html. After
- this brief bjam tutorial, we should have built the DLLs
- and run a python program using the extension.
-
-
- The tutorial example can be found in the directory: libs/python/example/tutorial.
- There, you can find:
-
-
-
- hello.cpp
-
-
- hello.py
-
-
- Jamroot
-
-
-
- The hello.cpp file is our C++ hello world example. The
- Jamroot is a minimalist bjam script
- that builds the DLLs for us. Finally, hello.py is our Python
- program that uses the extension in hello.cpp.
-
-
- Before anything else, you should have the bjam executable in your boost directory
- or somewhere in your path such that bjam can be executed
- in the command line. Pre-built Boost.Jam executables are available for most
- platforms. The complete list of Bjam executables can be found here.
-
-
-
- Let's Jam!
-
-
-
-
-
- Here is our minimalist
- Jamroot file. Simply copy the file and tweak use-project boost
- to where your boost root directory is and your OK.
-
-
- The comments contained in the Jamrules file above should be sufficient to get
- you going.
-
-
-
- Running bjam
-
-
- bjam is run using your operating system's command line
- interpreter.
-
-
- Start it up.
-
-
- A file called user-config.jam in your home directory is used to configure your
- tools. In Windows, your home directory can be found by typing:
-
-
ECHO %HOMEDRIVE%%HOMEPATH%
-
-
- into a command prompt window. Your file should at least have the rules for
- your compiler and your python installation. A specific example of this on Windows
- would be:
-
- The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools.
- The second rule provides information on Python, its version and where it is
- located. The above assumes that the Python installation is in C:dev/tools\/Python.
- If you have one fairly "standard" python installation for your platform,
- you might not need to do this.
-
-
- Now we are ready... Be sure to cd to libs/python/example/tutorial
- where the tutorial "hello.cpp" and the "Jamroot"
- is situated.
-
- In C++, and STL in particular, we see iterators everywhere. Python also has
- iterators, but these are two very different beasts.
-
-
- C++ iterators:
-
-
-
- C++ has 5 type categories (random-access, bidirectional, forward, input,
- output)
-
-
- There are 2 Operation categories: reposition, access
-
-
- A pair of iterators is needed to represent a (first/last) range.
-
-
-
- Python Iterators:
-
-
-
- 1 category (forward)
-
-
- 1 operation category (next())
-
-
- Raises StopIteration exception at end
-
-
-
- The typical Python iteration protocol: for y
- in x... is as follows:
-
-
iter=x.__iter__()# get iterator
-try:
- while1:
- y=iter.next()# get each item
- ...# process y
-exceptStopIteration:pass# iterator exhausted
-
-
- Boost.Python provides some mechanisms to make C++ iterators play along nicely
- as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that
- is compatible with the Python iteration protocol. For example:
-
- So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
- we wish to go the other way, though: we'd like to pass a Python sequence to
- an STL algorithm or use it to initialize an STL container. We need to make
- a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>.
- Consider how we might implement a function that exposes std::list<int>::assign() to Python:
-
-
template<typenameT>
-voidlist_assign(std::list<T>&l,objecto){
- // Turn a Python sequence into an STL input range
- stl_input_iterator<T>begin(o),end;
- l.assign(begin,end);
-}
-
-// Part of the wrapper for list<int>
-class_<std::list<int>>("list_int")
- .def("assign",&list_assign<int>)
- // ...
- ;
-
-
- Now in Python, we can assign any integer sequence to list_int
- objects:
-
- Python is dynamically typed, unlike C++ which is statically typed. Python variables
- may hold an integer, a float, list, dict, tuple, str, long etc., among other
- things. In the viewpoint of Boost.Python and C++, these Pythonic variables
- are just instances of class object. We will see in this
- chapter how to deal with Python objects.
-
-
- As mentioned, one of the goals of Boost.Python is to provide a bidirectional
- mapping between C++ and Python while maintaining the Python feel. Boost.Python
- C++ objects are as close as possible to Python. This should
- minimize the learning curve significantly.
-
-
-
-
-
-
-Basic Interface
-
- Class object wraps PyObject*. All the
- intricacies of dealing with PyObjects such as managing
- reference counting are handled by the object class. C++
- object interoperability is seamless. Boost.Python C++ objects
- can in fact be explicitly constructed from any C++ object.
-
- Apart from cosmetic differences due to the fact that we are writing the code
- in C++, the look and feel should be immediately apparent to the Python coder.
-
-
-
-
-Derived Object types
-
- Boost.Python comes with a set of derived object types
- corresponding to that of Python's:
-
-
-
- list
-
-
- dict
-
-
- tuple
-
-
- str
-
-
- long_
-
-
- enum
-
-
-
- These derived object types act like real Python types.
- For instance:
-
-
str(1)==>"1"
-
-
- Wherever appropriate, a particular derived object has
- corresponding Python type's methods. For instance, dict
- has a keys() method:
-
-
d.keys()
-
-
- make_tuple is provided for declaring tuple literals.
- Example:
-
-
make_tuple(123,'D',"Hello, World",0.0);
-
-
- In C++, when Boost.Python objects are used as arguments
- to functions, subtype matching is required. For example, when a function
- f, as declared below, is wrapped, it will only accept
- instances of Python's str type and subtypes.
-
-
voidf(strname)
-{
- objectn2=name.attr("upper")();// NAME = name.upper()
- strNAME=name.upper();// better
- objectmsg="%s is bigger than %s"%make_tuple(NAME,name);
-}
-
-
- In finer detail:
-
-
strNAME=name.upper();
-
-
- Illustrates that we provide versions of the str type's methods as C++ member
- functions.
-
-
objectmsg="%s is bigger than %s"%make_tuple(NAME,name);
-
-
- Demonstrates that you can write the C++ equivalent of "format"
- % x,y,z in Python, which is useful since there's no easy way to
- do that in std C++.
-
-
-
-
- Beware the common pitfall
- of forgetting that the constructors of most of Python's mutable types make
- copies, just as in Python.
-
-
-
- Python:
-
-
>>>d=dict(x.__dict__)# copies x.__dict__
->>>d['whatever']=3# modifies the copy
-
-
- C++:
-
-
dictd(x.attr("__dict__"));// copies x.__dict__
-d['whatever']=3;// modifies the copy
-
-
-
- class_<T> as objects
-
-
- Due to the dynamic nature of Boost.Python objects, any class_<T>
- may also be one of these types! The following code snippet wraps the class
- (type) object.
-
-
- We can use this to create wrapped instances. Example:
-
- At some point, we will need to get C++ values out of object instances. This
- can be achieved with the extract<T> function. Consider
- the following:
-
-
doublex=o.attr("length");// compile error
-
-
- In the code above, we got a compiler error because Boost.Python object
- can't be implicitly converted to doubles. Instead, what
- we wanted to do above can be achieved by writing:
-
- The first line attempts to extract the "length" attribute of the
- Boost.Python object. The second line attempts to extract
- the Vec2 object from held by the Boost.Python object.
-
-
- Take note that we said "attempt to" above. What if the Boost.Python
- object does not really hold a Vec2
- type? This is certainly a possibility considering the dynamic nature of Python
- objects. To be on the safe side, if the C++ type can't
- be extracted, an appropriate exception is thrown. To avoid an exception,
- we need to test for extractibility:
-
- Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
- has no enum type, we'll often want to expose our C++ enums
- to Python as an int. Boost.Python's enum facility makes
- this easy while taking care of the proper conversions from Python's dynamic
- typing to C++'s strong static typing (in C++, ints cannot be implicitly converted
- to enums). To illustrate, given a C++ enum:
-
- can be used to expose to Python. The new enum type is created in the current
- scope(), which is usually the current module. The snippet
- above creates a Python class derived from Python's int
- type which is associated with the C++ type passed as its first parameter.
-
-
-
-
-
Note
-
-
-
- what is a scope?
-
-
- The scope is a class that has an associated global Python object which
- controls the Python namespace in which new extension classes and wrapped
- functions will be defined as attributes. Details can be found here.
-
-
-
-
- You can access those values in Python as
-
-
>>>my_module.choice.red
-my_module.choice.red
-
-
- where my_module is the module where the enum is declared. You can also create
- a new scope around a class:
-
- Here are presented some useful techniques that you can use while wrapping code
- with Boost.Python.
-
-
-
-Creating Packages
-
- A Python package is a collection of modules that provide to the user a certain
- functionality. If you're not familiar on how to create packages, a good introduction
- to them is provided in the Python
- Tutorial.
-
-
- But we are wrapping C++ code, using Boost.Python. How can we provide a nice
- package interface to our users? To better explain some concepts, let's work
- with an example.
-
-
- We have a C++ library that works with sounds: reading and writing various
- formats, applying filters to the sound data, etc. It is named (conveniently)
- sounds. Our library already has a neat C++ namespace hierarchy,
- like so:
-
-
sounds::core
-sounds::io
-sounds::filters
-
-
- We would like to present this same hierarchy to the Python user, allowing
- him to write code like this:
-
-
importsounds.filters
-sounds.filters.echo(...)# echo is a C++ function
-
-
- The first step is to write the wrapping code. We have to export each module
- separately with Boost.Python, like this:
-
- Compiling these files will generate the following Python extensions: core.pyd,
- io.pyd and filters.pyd.
-
-
-
-
-
Note
-
-
- The extension .pyd is used for python extension modules,
- which are just shared libraries. Using the default for your system, like
- .so for Unix and .dll for Windows,
- works just as well.
-
-
-
- Now, we create this directory structure for our Python package:
-
- The file __init__.py is what tells Python that the directory
- sounds/ is actually a Python package. It can be a empty
- file, but can also perform some magic, that will be shown later.
-
-
- Now our package is ready. All the user has to do is put sounds
- into his PYTHONPATH
- and fire up the interpreter:
-
- This is the simplest way to create hierarchies of packages, but it is not
- very flexible. What if we want to add a pure Python
- function to the filters package, for instance, one that applies 3 filters
- in a sound object at once? Sure, you can do this in C++ and export it, but
- why not do so in Python? You don't have to recompile the extension modules,
- plus it will be easier to write it.
-
-
- If we want this flexibility, we will have to complicate our package hierarchy
- a little. First, we will have to change the name of the extension modules:
-
-
/* file core.cpp */
-BOOST_PYTHON_MODULE(_core)
-{
- ...
- /* export everything in the sounds::core namespace */
-}
-
-
- Note that we added an underscore to the module name. The filename will have
- to be changed to _core.pyd as well, and we do the same
- to the other extension modules. Now, we change our package hierarchy like
- so:
-
- Note that we created a directory for each extension module, and added a __init__.py
- to each one. But if we leave it that way, the user will have to access the
- functions in the core module with this syntax:
-
- which is not what we want. But here enters the __init__.py
- magic: everything that is brought to the __init__.py namespace
- can be accessed directly by the user. So, all we have to do is bring the
- entire namespace from _core.pyd to core/__init__.py.
- So add this line of code to sounds/core/__init__.py:
-
-
from_coreimport*
-
-
- We do the same for the other packages. Now the user accesses the functions
- and classes in the extension modules like before:
-
- with the additional benefit that we can easily add pure Python functions
- to any module, in a way that the user can't tell the difference between a
- C++ function and a Python function. Let's add a pure
- Python function, echo_noise, to the filters
- package. This function applies both the echo and noise
- filters in sequence in the given sound object. We create
- a file named sounds/filters/echo_noise.py and code our
- function:
-
- Thanks to Python's flexibility, you can easily add new methods to a class,
- even after it was already created:
-
-
>>>classC(object):pass
->>>
->>># a regular function
->>>defC_str(self):return'A C instance!'
->>>
->>># now we turn it in a member function
->>>C.__str__=C_str
->>>
->>>c=C()
->>>printc
-ACinstance!
->>>C_str(c)
-ACinstance!
-
-
- Yes, Python rox.
-
-
- We can do the same with classes that were wrapped with Boost.Python. Suppose
- we have a class point in C++:
-
- If we are using the technique from the previous session, Creating
- Packages, we can code directly into geom/__init__.py:
-
-
from_geomimport*
-
-# a regular function
-defpoint_str(self):
- returnstr((self.x,self.y))
-
-# now we turn it into a member function
-point.__str__=point_str
-
-
- All point instances created from C++ will
- also have this member function! This technique has several advantages:
-
-
-
- Cut down compile times to zero for these additional functions
-
-
- Reduce the memory footprint to virtually zero
-
-
- Minimize the need to recompile
-
-
- Rapid prototyping (you can move the code to C++ if required without changing
- the interface)
-
-
-
- You can even add a little syntactic sugar with the use of metaclasses. Let's
- create a special metaclass that "injects" methods in other classes.
-
-
# The one Boost.Python uses for all wrapped classes.
-# You can use here any class exported by Boost instead of "point"
-BoostPythonMetaclass=point.__class__
-
-classinjector(object):
- class__metaclass__(BoostPythonMetaclass):
- def__init__(self,name,bases,dict):
- forbinbases:
- iftype(b)notin(self,type):
- fork,vindict.items():
- setattr(b,k,v)
- returntype.__init__(self,name,bases,dict)
-
-# inject some methods in the point foo
-classmore_point(injector,point):
- def__repr__(self):
- return'Point(x=%s, y=%s)'%(self.x,self.y)
- deffoo(self):
- print'foo!'
-
- In this simple case there is not much gained, but for constructurs with many
- overloads and/or arguments this is often a great simplification, again with
- virtually zero memory footprint and zero compile-time overhead for the keyword
- support.
-
-
-
-
-Reducing Compiling Time
-
- If you have ever exported a lot of classes, you know that it takes quite
- a good time to compile the Boost.Python wrappers. Plus the memory consumption
- can easily become too high. If this is causing you problems, you can split
- the class_ definitions in multiple files:
-
- This method is recommended too if you are developing the C++ library and
- exporting it to Python at the same time: changes in a class will only demand
- the compilation of a single cpp, instead of the entire wrapper code.
-
-
-
-
-
Note
-
-
- If you're exporting your classes with Pyste,
- take a look at the --multiple option, that generates
- the wrappers in various files as demonstrated here.
-
-
-
-
-
-
Note
-
-
- This method is useful too if you are getting the error message "fatal
- error C1204:Compiler limit:internal structure overflow"
- when compiling a large source file, as explained in the FAQ.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/tutorial/doc/tutorial.qbk b/doc/tutorial/doc/tutorial.qbk
deleted file mode 100644
index 10a45220..00000000
--- a/doc/tutorial/doc/tutorial.qbk
+++ /dev/null
@@ -1,1985 +0,0 @@
-[library python
- [version 2.0]
- [authors [de Guzman, Joel], [Abrahams, David]]
- [copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams]
- [category inter-language support]
- [purpose
- Reflects C++ classes and functions into Python
- ]
- [license
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
-
- http://www.boost.org/LICENSE_1_0.txt
- )
- ]
-]
-
-[/ QuickBook Document version 0.9 ]
-
-[def __note__ [$images/note.png]]
-[def __alert__ [$images/alert.png]]
-[def __tip__ [$images/tip.png]]
-[def :-) [$images/smiley.png]]
-[def __jam__ [$images/jam.png]]
-
-[section QuickStart]
-
-The Boost Python Library is a framework for interfacing Python and
-C++. It allows you to quickly and seamlessly expose C++ classes
-functions and objects to Python, and vice-versa, using no special
-tools -- just your C++ compiler. It is designed to wrap C++ interfaces
-non-intrusively, so that you should not have to change the C++ code at
-all in order to wrap it, making Boost.Python ideal for exposing
-3rd-party libraries to Python. The library's use of advanced
-metaprogramming techniques simplifies its syntax for users, so that
-wrapping code takes on the look of a kind of declarative interface
-definition language (IDL).
-
-[h2 Hello World]
-
-Following C/C++ tradition, let's start with the "hello, world". A C++
-Function:
-
- char const* greet()
- {
- return "hello, world";
- }
-
-can be exposed to Python by writing a Boost.Python wrapper:
-
- #include
-
- BOOST_PYTHON_MODULE(hello_ext)
- {
- using namespace boost::python;
- def("greet", greet);
- }
-
-That's it. We're done. We can now build this as a shared library. The
-resulting DLL is now visible to Python. Here's a sample Python session:
-
-[python]
-
- >>> import hello_ext
- >>> print hello_ext.greet()
- hello, world
-
-[c++]
-
-[:['[*Next stop... Building your Hello World module from start to finish...]]]
-
-[endsect]
-[section:hello Building Hello World]
-
-[h2 From Start To Finish]
-
-Now the first thing you'd want to do is to build the Hello World module and
-try it for yourself in Python. In this section, we will outline the steps
-necessary to achieve that. We will use the build tool that comes bundled
-with every boost distribution: [*bjam].
-
-[note [*Building without bjam]
-
-Besides bjam, there are of course other ways to get your module built.
-What's written here should not be taken as "the one and only way".
-There are of course other build tools apart from [^bjam].
-
-Take note however that the preferred build tool for Boost.Python is bjam.
-There are so many ways to set up the build incorrectly. Experience shows
-that 90% of the "I can't build Boost.Python" problems come from people
-who had to use a different tool.
-]
-
-We will skip over the details. Our objective will be to simply create
-the hello world module and run it in Python. For a complete reference to
-building Boost.Python, check out: [@../../../building.html
-building.html]. After this brief ['bjam] tutorial, we should have built
-the DLLs and run a python program using the extension.
-
-The tutorial example can be found in the directory:
-[^libs/python/example/tutorial]. There, you can find:
-
-* hello.cpp
-* hello.py
-* Jamroot
-
-The [^hello.cpp] file is our C++ hello world example. The [^Jamroot] is
-a minimalist ['bjam] script that builds the DLLs for us. Finally,
-[^hello.py] is our Python program that uses the extension in
-[^hello.cpp].
-
-Before anything else, you should have the bjam executable in your boost
-directory or somewhere in your path such that [^bjam] can be executed in
-the command line. Pre-built Boost.Jam executables are available for most
-platforms. The complete list of Bjam executables can be found
-[@http://sourceforge.net/project/showfiles.php?group_id=7586 here].
-
-[h2 Let's Jam!]
-__jam__
-
-[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot
-file. Simply copy the file and tweak [^use-project boost] to where your
-boost root directory is and your OK.
-
-The comments contained in the Jamrules file above should be sufficient
-to get you going.
-
-[h2 Running bjam]
-
-['bjam] is run using your operating system's command line interpreter.
-
-[:Start it up.]
-
-A file called user-config.jam in your home directory is used to
-configure your tools. In Windows, your home directory can be found by
-typing:
-
-[pre
-ECHO %HOMEDRIVE%%HOMEPATH%
-]
-
-into a command prompt window. Your file should at least have the rules
-for your compiler and your python installation. A specific example of
-this on Windows would be:
-
-[pre
-# MSVC configuration
-using msvc : 8.0 ;
-
-# Python configuration
-using python : 2.4 : C:/dev/tools/Python/ ;
-]
-
-The first rule tells Bjam to use the MSVC 8.0 compiler and associated
-tools. The second rule provides information on Python, its version and
-where it is located. The above assumes that the Python installation is
-in [^C:/dev/tools\/Python/]. If you have one fairly "standard" python
-installation for your platform, you might not need to do this.
-
-Now we are ready... Be sure to [^cd] to [^libs/python/example/tutorial]
-where the tutorial [^"hello.cpp"] and the [^"Jamroot"] is situated.
-
-Finally:
-
- bjam
-
-It should be building now:
-
-[pre
-cd C:\dev\boost\libs\python\example\tutorial
-bjam
-...patience...
-...found 1101 targets...
-...updating 35 targets...
-]
-
-And so on... Finally:
-
-[pre
- Creating library /path-to-boost_python.dll/
- Creating library /path-to-'''hello_ext'''.exp/
-'''**passed**''' ... hello.test
-...updated 35 targets...
-]
-
-Or something similar. If all is well, you should now have built the DLLs and
-run the Python program.
-
-[:[*There you go... Have fun!]]
-
-[endsect]
-[section:exposing Exposing Classes]
-
-Now let's expose a C++ class to Python.
-
-Consider a C++ class/struct that we want to expose to Python:
-
- struct World
- {
- void set(std::string msg) { this->msg = msg; }
- std::string greet() { return msg; }
- std::string msg;
- };
-
-We can expose this to Python by writing a corresponding Boost.Python
-C++ Wrapper:
-
- #include
- using namespace boost::python;
-
- BOOST_PYTHON_MODULE(hello)
- {
- class_("World")
- .def("greet", &World::greet)
- .def("set", &World::set)
- ;
- }
-
-Here, we wrote a C++ class wrapper that exposes the member functions
-[^greet] and [^set]. Now, after building our module as a shared library, we
-may use our class [^World] in Python. Here's a sample Python session:
-
-[python]
-
- >>> import hello
- >>> planet = hello.World()
- >>> planet.set('howdy')
- >>> planet.greet()
- 'howdy'
-
-[section Constructors]
-
-Our previous example didn't have any explicit constructors.
-Since [^World] is declared as a plain struct, it has an implicit default
-constructor. Boost.Python exposes the default constructor by default,
-which is why we were able to write
-
- >>> planet = hello.World()
-
-We may wish to wrap a class with a non-default constructor. Let us
-build on our previous example:
-
-[c++]
-
- struct World
- {
- World(std::string msg): msg(msg) {} // added constructor
- void set(std::string msg) { this->msg = msg; }
- std::string greet() { return msg; }
- std::string msg;
- };
-
-This time [^World] has no default constructor; our previous
-wrapping code would fail to compile when the library tried to expose
-it. We have to tell [^class_] about the constructor we want to
-expose instead.
-
- #include
- using namespace boost::python;
-
- BOOST_PYTHON_MODULE(hello)
- {
- class_("World", init())
- .def("greet", &World::greet)
- .def("set", &World::set)
- ;
- }
-
-[^init()] exposes the constructor taking in a
-[^std::string] (in Python, constructors are spelled
-"[^"__init__"]").
-
-We can expose additional constructors by passing more [^init<...>]s to
-the [^def()] member function. Say for example we have another World
-constructor taking in two doubles:
-
- class_("World", init())
- .def(init())
- .def("greet", &World::greet)
- .def("set", &World::set)
- ;
-
-On the other hand, if we do not wish to expose any constructors at
-all, we may use [^no_init] instead:
-
- class_("Abstract", no_init)
-
-This actually adds an [^__init__] method which always raises a
-Python RuntimeError exception.
-
-[endsect]
-[section Class Data Members]
-
-Data members may also be exposed to Python so that they can be
-accessed as attributes of the corresponding Python class. Each data
-member that we wish to be exposed may be regarded as [*read-only] or
-[*read-write]. Consider this class [^Var]:
-
- struct Var
- {
- Var(std::string name) : name(name), value() {}
- std::string const name;
- float value;
- };
-
-Our C++ [^Var] class and its data members can be exposed to Python:
-
- class_("Var", init())
- .def_readonly("name", &Var::name)
- .def_readwrite("value", &Var::value);
-
-Then, in Python, assuming we have placed our Var class inside the namespace
-hello as we did before:
-
-[python]
-
- >>> x = hello.Var('pi')
- >>> x.value = 3.14
- >>> print x.name, 'is around', x.value
- pi is around 3.14
-
-Note that [^name] is exposed as [*read-only] while [^value] is exposed
-as [*read-write].
-
- >>> x.name = 'e' # can't change name
- Traceback (most recent call last):
- File "", line 1, in ?
- AttributeError: can't set attribute
-
-[endsect]
-[section Class Properties]
-
-In C++, classes with public data members are usually frowned
-upon. Well designed classes that take advantage of encapsulation hide
-the class' data members. The only way to access the class' data is
-through access (getter/setter) functions. Access functions expose class
-properties. Here's an example:
-
-[c++]
-
- struct Num
- {
- Num();
- float get() const;
- void set(float value);
- ...
- };
-
-However, in Python attribute access is fine; it doesn't neccessarily break
-encapsulation to let users handle attributes directly, because the
-attributes can just be a different syntax for a method call. Wrapping our
-[^Num] class using Boost.Python:
-
- class_("Num")
- .add_property("rovalue", &Num::get)
- .add_property("value", &Num::get, &Num::set);
-
-And at last, in Python:
-
-[python]
-
- >>> x = Num()
- >>> x.value = 3.14
- >>> x.value, x.rovalue
- (3.14, 3.14)
- >>> x.rovalue = 2.17 # error!
-
-Take note that the class property [^rovalue] is exposed as [*read-only]
-since the [^rovalue] setter member function is not passed in:
-
-[c++]
-
- .add_property("rovalue", &Num::get)
-
-[endsect]
-[section Inheritance]
-
-In the previous examples, we dealt with classes that are not polymorphic.
-This is not often the case. Much of the time, we will be wrapping
-polymorphic classes and class hierarchies related by inheritance. We will
-often have to write Boost.Python wrappers for classes that are derived from
-abstract base classes.
-
-Consider this trivial inheritance structure:
-
- struct Base { virtual ~Base(); };
- struct Derived : Base {};
-
-And a set of C++ functions operating on [^Base] and [^Derived] object
-instances:
-
- void b(Base*);
- void d(Derived*);
- Base* factory() { return new Derived; }
-
-We've seen how we can wrap the base class [^Base]:
-
- class_("Base")
- /*...*/
- ;
-
-Now we can inform Boost.Python of the inheritance relationship between
-[^Derived] and its base class [^Base]. Thus:
-
- class_ >("Derived")
- /*...*/
- ;
-
-Doing so, we get some things for free:
-
-# Derived automatically inherits all of Base's Python methods
- (wrapped C++ member functions)
-# [*If] Base is polymorphic, [^Derived] objects which have been passed to
- Python via a pointer or reference to [^Base] can be passed where a pointer
- or reference to [^Derived] is expected.
-
-Now, we will expose the C++ free functions [^b] and [^d] and [^factory]:
-
- def("b", b);
- def("d", d);
- def("factory", factory);
-
-Note that free function [^factory] is being used to generate new
-instances of class [^Derived]. In such cases, we use
-[^return_value_policy] to instruct Python to adopt
-the pointer to [^Base] and hold the instance in a new Python [^Base]
-object until the the Python object is destroyed. We will see more of
-Boost.Python [link python.call_policies call policies] later.
-
- // Tell Python to take ownership of factory's result
- def("factory", factory,
- return_value_policy());
-
-[endsect]
-
-[section Class Virtual Functions]
-
-In this section, we will learn how to make functions behave polymorphically
-through virtual functions. Continuing our example, let us add a virtual function
-to our [^Base] class:
-
- struct Base
- {
- virtual ~Base() {}
- virtual int f() = 0;
- };
-
-One of the goals of Boost.Python is to be minimally intrusive on an existing C++
-design. In principle, it should be possible to expose the interface for a 3rd
-party library without changing it. It is not ideal to add anything to our class
-`Base`. Yet, when you have a virtual function that's going to be overridden in
-Python and called polymorphically *from C++*, we'll need to add some
-scaffoldings to make things work properly. What we'll do is write a class
-wrapper that derives from `Base` that will unintrusively hook into the virtual
-functions so that a Python override may be called:
-
- struct BaseWrap : Base, wrapper
- {
- int f()
- {
- return this->get_override("f")();
- }
- };
-
-Notice too that in addition to inheriting from `Base`, we also multiply-
-inherited `wrapper` (See [@../../../v2/wrapper.html Wrapper]). The
-`wrapper` template makes the job of wrapping classes that are meant to
-overridden in Python, easier.
-
-[blurb __alert__ [*MSVC6/7 Workaround]
-
-If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:
-
-`return call(this->get_override("f").ptr());`.]
-
-BaseWrap's overridden virtual member function `f` in effect calls the
-corresponding method of the Python object through `get_override`.
-
-Finally, exposing `Base`:
-
- class_("Base")
- .def("f", pure_virtual(&Base::f))
- ;
-
-`pure_virtual` signals Boost.Python that the function `f` is a pure virtual
-function.
-
-[note [*member function and methods]
-
-Python, like many object oriented languages uses the term [*methods].
-Methods correspond roughly to C++'s [*member functions]]
-
-[endsect]
-
-[section Virtual Functions with Default Implementations]
-
-We've seen in the previous section how classes with pure virtual functions are
-wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper]
-facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
-mechanism is a bit different.
-
-Recall that in the [link python.class_virtual_functions previous section], we
-wrapped a class with a pure virtual function that we then implemented in C++, or
-Python classes derived from it. Our base class:
-
- struct Base
- {
- virtual int f() = 0;
- };
-
-had a pure virtual function [^f]. If, however, its member function [^f] was
-not declared as pure virtual:
-
- struct Base
- {
- virtual ~Base() {}
- virtual int f() { return 0; }
- };
-
-We wrap it this way:
-
- struct BaseWrap : Base, wrapper
- {
- int f()
- {
- if (override f = this->get_override("f"))
- return f(); // *note*
- return Base::f();
- }
-
- int default_f() { return this->Base::f(); }
- };
-
-Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
-override for `f`. If none, then we call `Base::f()`.
-
-[blurb __alert__ [*MSVC6/7 Workaround]
-
-If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
-with the `*note*` as:
-
-`return call(f.ptr());`.]
-
-Finally, exposing:
-
- class_("Base")
- .def("f", &Base::f, &BaseWrap::default_f)
- ;
-
-Take note that we expose both `&Base::f` and `&BaseWrap::default_f`.
-Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the
-forwarding function to its default implementation [^default_f]. There's a
-special [^def] function for this purpose.
-
-In Python, the results would be as expected:
-
-[python]
-
- >>> base = Base()
- >>> class Derived(Base):
- ... def f(self):
- ... return 42
- ...
- >>> derived = Derived()
-
-Calling [^base.f()]:
-
- >>> base.f()
- 0
-
-Calling [^derived.f()]:
-
- >>> derived.f()
- 42
-
-[endsect]
-[section Class Operators/Special Functions]
-
-[h2 Python Operators]
-
-C is well known for the abundance of operators. C++ extends this to the
-extremes by allowing operator overloading. Boost.Python takes advantage of
-this and makes it easy to wrap C++ operator-powered classes.
-
-Consider a file position class [^FilePos] and a set of operators that take
-on FilePos instances:
-
-[c++]
-
- class FilePos { /*...*/ };
-
- FilePos operator+(FilePos, int);
- FilePos operator+(int, FilePos);
- int operator-(FilePos, FilePos);
- FilePos operator-(FilePos, int);
- FilePos& operator+=(FilePos&, int);
- FilePos& operator-=(FilePos&, int);
- bool operator<(FilePos, FilePos);
-
-The class and the various operators can be mapped to Python rather easily
-and intuitively:
-
- class_("FilePos")
- .def(self + int()) // __add__
- .def(int() + self) // __radd__
- .def(self - self) // __sub__
- .def(self - int()) // __sub__
- .def(self += int()) // __iadd__
- .def(self -= other())
- .def(self < self); // __lt__
-
-The code snippet above is very clear and needs almost no explanation at
-all. It is virtually the same as the operators' signatures. Just take
-note that [^self] refers to FilePos object. Also, not every class [^T] that
-you might need to interact with in an operator expression is (cheaply)
-default-constructible. You can use [^other()] in place of an actual
-[^T] instance when writing "self expressions".
-
-[h2 Special Methods]
-
-Python has a few more ['Special Methods]. Boost.Python supports all of the
-standard special method names supported by real Python class instances. A
-similar set of intuitive interfaces can also be used to wrap C++ functions
-that correspond to these Python ['special functions]. Example:
-
- class Rational
- { public: operator double() const; };
-
- Rational pow(Rational, Rational);
- Rational abs(Rational);
- ostream& operator<<(ostream&,Rational);
-
- class_("Rational")
- .def(float_(self)) // __float__
- .def(pow(self, other)) // __pow__
- .def(abs(self)) // __abs__
- .def(str(self)) // __str__
- ;
-
-Need we say more?
-
-[note What is the business of `operator<<`?
-Well, the method `str` requires the `operator<<` to do its work (i.e.
-`operator<<` is used by the method defined by `def(str(self))`.]
-
-[endsect]
-[endsect] [/ Exposing Classes ]
-
-[section Functions]
-
-In this chapter, we'll look at Boost.Python powered functions in closer
-detail. We will see some facilities to make exposing C++ functions to
-Python safe from potential pifalls such as dangling pointers and
-references. We will also see facilities that will make it even easier for
-us to expose C++ functions that take advantage of C++ features such as
-overloading and default arguments.
-
-[:['Read on...]]
-
-But before you do, you might want to fire up Python 2.2 or later and type
-[^>>> import this].
-
-[pre
->>> import this
-The Zen of Python, by Tim Peters
-Beautiful is better than ugly.
-Explicit is better than implicit.
-Simple is better than complex.
-Complex is better than complicated.
-Flat is better than nested.
-Sparse is better than dense.
-Readability counts.
-Special cases aren't special enough to break the rules.
-Although practicality beats purity.
-Errors should never pass silently.
-Unless explicitly silenced.
-In the face of ambiguity, refuse the temptation to guess.
-There should be one-- and preferably only one --obvious way to do it
-Although that way may not be obvious at first unless you're Dutch.
-Now is better than never.
-Although never is often better than *right* now.
-If the implementation is hard to explain, it's a bad idea.
-If the implementation is easy to explain, it may be a good idea.
-Namespaces are one honking great idea -- let's do more of those!
-]
-
-[section Call Policies]
-
-In C++, we often deal with arguments and return types such as pointers
-and references. Such primitive types are rather, ummmm, low level and
-they really don't tell us much. At the very least, we don't know the
-owner of the pointer or the referenced object. No wonder languages
-such as Java and Python never deal with such low level entities. In
-C++, it's usually considered a good practice to use smart pointers
-which exactly describe ownership semantics. Still, even good C++
-interfaces use raw references and pointers sometimes, so Boost.Python
-must deal with them. To do this, it may need your help. Consider the
-following C++ function:
-
- X& f(Y& y, Z* z);
-
-How should the library wrap this function? A naive approach builds a
-Python X object around result reference. This strategy might or might
-not work out. Here's an example where it didn't
-
- >>> x = f(y, z) # x refers to some C++ X
- >>> del y
- >>> x.some_method() # CRASH!
-
-What's the problem?
-
-Well, what if f() was implemented as shown below:
-
- X& f(Y& y, Z* z)
- {
- y.z = z;
- return y.x;
- }
-
-The problem is that the lifetime of result X& is tied to the lifetime
-of y, because the f() returns a reference to a member of the y
-object. This idiom is is not uncommon and perfectly acceptable in the
-context of C++. However, Python users should not be able to crash the
-system just by using our C++ interface. In this case deleting y will
-invalidate the reference to X. We have a dangling reference.
-
-Here's what's happening:
-
-# [^f] is called passing in a reference to [^y] and a pointer to [^z]
-# A reference to [^y.x] is returned
-# [^y] is deleted. [^x] is a dangling reference
-# [^x.some_method()] is called
-# [*BOOM!]
-
-We could copy result into a new object:
-
-[python]
-
- >>> f(y, z).set(42) # Result disappears
- >>> y.x.get() # No crash, but still bad
- 3.14
-
-This is not really our intent of our C++ interface. We've broken our
-promise that the Python interface should reflect the C++ interface as
-closely as possible.
-
-Our problems do not end there. Suppose Y is implemented as follows:
-
-[c++]
-
- struct Y
- {
- X x; Z* z;
- int z_value() { return z->value(); }
- };
-
-Notice that the data member [^z] is held by class Y using a raw
-pointer. Now we have a potential dangling pointer problem inside Y:
-
- >>> x = f(y, z) # y refers to z
- >>> del z # Kill the z object
- >>> y.z_value() # CRASH!
-
-For reference, here's the implementation of [^f] again:
-
- X& f(Y& y, Z* z)
- {
- y.z = z;
- return y.x;
- }
-
-Here's what's happening:
-
-# [^f] is called passing in a reference to [^y] and a pointer to [^z]
-# A pointer to [^z] is held by [^y]
-# A reference to [^y.x] is returned
-# [^z] is deleted. [^y.z] is a dangling pointer
-# [^y.z_value()] is called
-# [^z->value()] is called
-# [*BOOM!]
-
-[h2 Call Policies]
-
-Call Policies may be used in situations such as the example detailed above.
-In our example, [^return_internal_reference] and [^with_custodian_and_ward]
-are our friends:
-
- def("f", f,
- return_internal_reference<1,
- with_custodian_and_ward<1, 2> >());
-
-What are the [^1] and [^2] parameters, you ask?
-
- return_internal_reference<1
-
-Informs Boost.Python that the first argument, in our case [^Y& y], is the
-owner of the returned reference: [^X&]. The "[^1]" simply specifies the
-first argument. In short: "return an internal reference [^X&] owned by the
-1st argument [^Y& y]".
-
- with_custodian_and_ward<1, 2>
-
-Informs Boost.Python that the lifetime of the argument indicated by ward
-(i.e. the 2nd argument: [^Z* z]) is dependent on the lifetime of the
-argument indicated by custodian (i.e. the 1st argument: [^Y& y]).
-
-It is also important to note that we have defined two policies above. Two
-or more policies can be composed by chaining. Here's the general syntax:
-
- policy1 > >
-
-Here is the list of predefined call policies. A complete reference detailing
-these can be found [@../../../v2/reference.html#models_of_call_policies here].
-
-* [*with_custodian_and_ward]: Ties lifetimes of the arguments
-* [*with_custodian_and_ward_postcall]: Ties lifetimes of the arguments and results
-* [*return_internal_reference]: Ties lifetime of one argument to that of result
-* [*return_value_policy with T one of:]
- * [*reference_existing_object]: naive (dangerous) approach
- * [*copy_const_reference]: Boost.Python v1 approach
- * [*copy_non_const_reference]:
- * [*manage_new_object]: Adopt a pointer and hold the instance
-
-[blurb :-) [*Remember the Zen, Luke:]
-
-"Explicit is better than implicit"
-
-"In the face of ambiguity, refuse the temptation to guess"
-]
-
-[endsect]
-[section Overloading]
-
-The following illustrates a scheme for manually wrapping an overloaded
-member functions. Of course, the same technique can be applied to wrapping
-overloaded non-member functions.
-
-We have here our C++ class:
-
- struct X
- {
- bool f(int a)
- {
- return true;
- }
-
- bool f(int a, double b)
- {
- return true;
- }
-
- bool f(int a, double b, char c)
- {
- return true;
- }
-
- int f(int a, int b, int c)
- {
- return a + b + c;
- };
- };
-
-Class X has 4 overloaded functions. We will start by introducing some
-member function pointer variables:
-
- bool (X::*fx1)(int) = &X::f;
- bool (X::*fx2)(int, double) = &X::f;
- bool (X::*fx3)(int, double, char)= &X::f;
- int (X::*fx4)(int, int, int) = &X::f;
-
-With these in hand, we can proceed to define and wrap this for Python:
-
- .def("f", fx1)
- .def("f", fx2)
- .def("f", fx3)
- .def("f", fx4)
-
-[endsect]
-[section Default Arguments]
-
-Boost.Python wraps (member) function pointers. Unfortunately, C++ function
-pointers carry no default argument info. Take a function [^f] with default
-arguments:
-
- int f(int, double = 3.14, char const* = "hello");
-
-But the type of a pointer to the function [^f] has no information
-about its default arguments:
-
- int(*g)(int,double,char const*) = f; // defaults lost!
-
-When we pass this function pointer to the [^def] function, there is no way
-to retrieve the default arguments:
-
- def("f", f); // defaults lost!
-
-Because of this, when wrapping C++ code, we had to resort to manual
-wrapping as outlined in the [link python.overloading previous section], or
-writing thin wrappers:
-
- // write "thin wrappers"
- int f1(int x) { return f(x); }
- int f2(int x, double y) { return f(x,y); }
-
- /*...*/
-
- // in module init
- def("f", f); // all arguments
- def("f", f2); // two arguments
- def("f", f1); // one argument
-
-When you want to wrap functions (or member functions) that either:
-
-* have default arguments, or
-* are overloaded with a common sequence of initial arguments
-
-[h2 BOOST_PYTHON_FUNCTION_OVERLOADS]
-
-Boost.Python now has a way to make it easier. For instance, given a function:
-
- int foo(int a, char b = 1, unsigned c = 2, double d = 3)
- {
- /*...*/
- }
-
-The macro invocation:
-
- BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
-
-will automatically create the thin wrappers for us. This macro will create
-a class [^foo_overloads] that can be passed on to [^def(...)]. The third
-and fourth macro argument are the minimum arguments and maximum arguments,
-respectively. In our [^foo] function the minimum number of arguments is 1
-and the maximum number of arguments is 4. The [^def(...)] function will
-automatically add all the foo variants for us:
-
- def("foo", foo, foo_overloads());
-
-[h2 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
-
-Objects here, objects there, objects here there everywhere. More frequently
-than anything else, we need to expose member functions of our classes to
-Python. Then again, we have the same inconveniences as before when default
-arguments or overloads with a common sequence of initial arguments come
-into play. Another macro is provided to make this a breeze.
-
-Like [^BOOST_PYTHON_FUNCTION_OVERLOADS],
-[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] may be used to automatically create
-the thin wrappers for wrapping member functions. Let's have an example:
-
- struct george
- {
- void
- wack_em(int a, int b = 0, char c = 'x')
- {
- /*...*/
- }
- };
-
-The macro invocation:
-
- BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
-
-will generate a set of thin wrappers for george's [^wack_em] member function
-accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and
-fourth macro argument). The thin wrappers are all enclosed in a class named
-[^george_overloads] that can then be used as an argument to [^def(...)]:
-
- .def("wack_em", &george::wack_em, george_overloads());
-
-See the [@../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
-for details.
-
-[h2 init and optional]
-
-A similar facility is provided for class constructors, again, with
-default arguments or a sequence of overloads. Remember [^init<...>]? For example,
-given a class X with a constructor:
-
- struct X
- {
- X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
- /*...*/
- }
-
-You can easily add this constructor to Boost.Python in one shot:
-
- .def(init >())
-
-Notice the use of [^init<...>] and [^optional<...>] to signify the default
-(optional arguments).
-
-[endsect]
-[section Auto-Overloading]
-
-It was mentioned in passing in the previous section that
-[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
-can also be used for overloaded functions and member functions with a
-common sequence of initial arguments. Here is an example:
-
- void foo()
- {
- /*...*/
- }
-
- void foo(bool a)
- {
- /*...*/
- }
-
- void foo(bool a, int b)
- {
- /*...*/
- }
-
- void foo(bool a, int b, char c)
- {
- /*...*/
- }
-
-Like in the previous section, we can generate thin wrappers for these
-overloaded functions in one-shot:
-
- BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
-
-Then...
-
- .def("foo", (void(*)(bool, int, char))0, foo_overloads());
-
-Notice though that we have a situation now where we have a minimum of zero
-(0) arguments and a maximum of 3 arguments.
-
-[h2 Manual Wrapping]
-
-It is important to emphasize however that [*the overloaded functions must
-have a common sequence of initial arguments]. Otherwise, our scheme above
-will not work. If this is not the case, we have to wrap our functions
-[link python.overloading manually].
-
-Actually, we can mix and match manual wrapping of overloaded functions and
-automatic wrapping through [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] and
-its sister, [^BOOST_PYTHON_FUNCTION_OVERLOADS]. Following up on our example
-presented in the section [link python.overloading on overloading], since the
-first 4 overload functins have a common sequence of initial arguments, we
-can use [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] to automatically wrap the
-first three of the [^def]s and manually wrap just the last. Here's
-how we'll do this:
-
- BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
-
-Create a member function pointers as above for both X::f overloads:
-
- bool (X::*fx1)(int, double, char) = &X::f;
- int (X::*fx2)(int, int, int) = &X::f;
-
-Then...
-
- .def("f", fx1, xf_overloads());
- .def("f", fx2)
-
-[endsect]
-[endsect] [/ Functions ]
-
-[section:object Object Interface]
-
-Python is dynamically typed, unlike C++ which is statically typed. Python
-variables may hold an integer, a float, list, dict, tuple, str, long etc.,
-among other things. In the viewpoint of Boost.Python and C++, these
-Pythonic variables are just instances of class [^object]. We will see in
-this chapter how to deal with Python objects.
-
-As mentioned, one of the goals of Boost.Python is to provide a
-bidirectional mapping between C++ and Python while maintaining the Python
-feel. Boost.Python C++ [^object]s are as close as possible to Python. This
-should minimize the learning curve significantly.
-
-[$images/python.png]
-
-[section Basic Interface]
-
-Class [^object] wraps [^PyObject*]. All the intricacies of dealing with
-[^PyObject]s such as managing reference counting are handled by the
-[^object] class. C++ object interoperability is seamless. Boost.Python C++
-[^object]s can in fact be explicitly constructed from any C++ object.
-
-To illustrate, this Python code snippet:
-
-[python]
-
- def f(x, y):
- if (y == 'foo'):
- x[3:7] = 'bar'
- else:
- x.items += y(3, x)
- return x
-
- def getfunc():
- return f;
-
-Can be rewritten in C++ using Boost.Python facilities this way:
-
-[c++]
-
- object f(object x, object y) {
- if (y == "foo")
- x.slice(3,7) = "bar";
- else
- x.attr("items") += y(3, x);
- return x;
- }
- object getfunc() {
- return object(f);
- }
-
-Apart from cosmetic differences due to the fact that we are writing the
-code in C++, the look and feel should be immediately apparent to the Python
-coder.
-
-[endsect]
-[section Derived Object types]
-
-Boost.Python comes with a set of derived [^object] types corresponding to
-that of Python's:
-
-* list
-* dict
-* tuple
-* str
-* long_
-* enum
-
-These derived [^object] types act like real Python types. For instance:
-
- str(1) ==> "1"
-
-Wherever appropriate, a particular derived [^object] has corresponding
-Python type's methods. For instance, [^dict] has a [^keys()] method:
-
- d.keys()
-
-[^make_tuple] is provided for declaring ['tuple literals]. Example:
-
- make_tuple(123, 'D', "Hello, World", 0.0);
-
-In C++, when Boost.Python [^object]s are used as arguments to functions,
-subtype matching is required. For example, when a function [^f], as
-declared below, is wrapped, it will only accept instances of Python's
-[^str] type and subtypes.
-
- void f(str name)
- {
- object n2 = name.attr("upper")(); // NAME = name.upper()
- str NAME = name.upper(); // better
- object msg = "%s is bigger than %s" % make_tuple(NAME,name);
- }
-
-In finer detail:
-
- str NAME = name.upper();
-
-Illustrates that we provide versions of the str type's methods as C++
-member functions.
-
- object msg = "%s is bigger than %s" % make_tuple(NAME,name);
-
-Demonstrates that you can write the C++ equivalent of [^"format" % x,y,z]
-in Python, which is useful since there's no easy way to do that in std C++.
-
-[blurb
- __alert__ [*Beware] the common pitfall of forgetting that the constructors
- of most of Python's mutable types make copies, just as in Python.
-]
-
-Python:
-[python]
-
- >>> d = dict(x.__dict__) # copies x.__dict__
- >>> d['whatever'] = 3 # modifies the copy
-
-C++:
-[c++]
-
- dict d(x.attr("__dict__")); // copies x.__dict__
- d['whatever'] = 3; // modifies the copy
-
-[h2 class_ as objects]
-
-Due to the dynamic nature of Boost.Python objects, any [^class_] may
-also be one of these types! The following code snippet wraps the class
-(type) object.
-
-We can use this to create wrapped instances. Example:
-
- object vec345 = (
- class_("Vec2", init())
- .def_readonly("length", &Point::length)
- .def_readonly("angle", &Point::angle)
- )(3.0, 4.0);
-
- assert(vec345.attr("length") == 5.0);
-
-[endsect]
-[section Extracting C++ objects]
-
-At some point, we will need to get C++ values out of object instances. This
-can be achieved with the [^extract] function. Consider the following:
-
- double x = o.attr("length"); // compile error
-
-In the code above, we got a compiler error because Boost.Python
-[^object] can't be implicitly converted to [^double]s. Instead, what
-we wanted to do above can be achieved by writing:
-
- double l = extract(o.attr("length"));
- Vec2& v = extract(o);
- assert(l == v.length());
-
-The first line attempts to extract the "length" attribute of the Boost.Python
-[^object]. The second line attempts to ['extract] the [^Vec2] object from held
-by the Boost.Python [^object].
-
-Take note that we said "attempt to" above. What if the Boost.Python [^object]
-does not really hold a [^Vec2] type? This is certainly a possibility considering
-the dynamic nature of Python [^object]s. To be on the safe side, if the C++ type
-can't be extracted, an appropriate exception is thrown. To avoid an exception,
-we need to test for extractibility:
-
- extract x(o);
- if (x.check()) {
- Vec2& v = x(); ...
-
-__tip__ The astute reader might have noticed that the [^extract]
-facility in fact solves the mutable copying problem:
-
- dict d = extract(x.attr("__dict__"));
- d["whatever"] = 3; // modifies x.__dict__ !
-
-
-[endsect]
-[section Enums]
-
-Boost.Python has a nifty facility to capture and wrap C++ enums. While
-Python has no [^enum] type, we'll often want to expose our C++ enums to
-Python as an [^int]. Boost.Python's enum facility makes this easy while
-taking care of the proper conversions from Python's dynamic typing to C++'s
-strong static typing (in C++, ints cannot be implicitly converted to
-enums). To illustrate, given a C++ enum:
-
- enum choice { red, blue };
-
-the construct:
-
- enum_("choice")
- .value("red", red)
- .value("blue", blue)
- ;
-
-can be used to expose to Python. The new enum type is created in the
-current [^scope()], which is usually the current module. The snippet above
-creates a Python class derived from Python's [^int] type which is
-associated with the C++ type passed as its first parameter.
-
-[note [*what is a scope?]
-
-The scope is a class that has an associated global Python object which
-controls the Python namespace in which new extension classes and wrapped
-functions will be defined as attributes. Details can be found
-[@../../../v2/scope.html here].]
-
-You can access those values in Python as
-
-[python]
-
- >>> my_module.choice.red
- my_module.choice.red
-
-where my_module is the module where the enum is declared. You can also
-create a new scope around a class:
-
-[c++]
-
- scope in_X = class_("X")
- .def( ... )
- .def( ... )
- ;
-
- // Expose X::nested as X.nested
- enum_("nested")
- .value("red", red)
- .value("blue", blue)
- ;
-
-[def Py_Initialize [@http://www.python.org/doc/current/api/initialization.html#l2h-652 Py_Initialize]]
-[def Py_Finalize [@http://www.python.org/doc/current/api/initialization.html#l2h-656 Py_Finalize]]
-[def Py_XINCREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-65 Py_XINCREF]]
-[def Py_XDECREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-67 Py_XDECREF]]
-[def PyImport_AppendInittab [@http://www.python.org/doc/current/api/importing.html#l2h-137 PyImport_AppendInittab]]
-[def PyImport_AddModule [@http://www.python.org/doc/current/api/importing.html#l2h-125 PyImport_AddModule]]
-[def PyModule_New [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-591 PyModule_New]]
-[def PyModule_GetDict [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-594 PyModule_GetDict]]
-
-[endsect]
-
-[section:creating_python_object Creating `boost::python::object` from `PyObject*`]
-
-When you want a `boost::python::object` to manage a pointer to `PyObject*` pyobj one does:
-
- boost::python::object o(boost::python::handle<>(pyobj));
-
-In this case, the `o` object, manages the `pyobj`, it won’t increase the reference count on construction.
-
-Otherwise, to use a borrowed reference:
-
- boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));
-
-In this case, `Py_INCREF` is called, so `pyobj` is not destructed when object o goes out of scope.
-
-[endsect] [/ creating_python_object ]
-
-[endsect] [/ Object Interface]
-
-[section Embedding]
-
-By now you should know how to use Boost.Python to call your C++ code from
-Python. However, sometimes you may need to do the reverse: call Python code
-from the C++-side. This requires you to ['embed] the Python interpreter
-into your C++ program.
-
-Currently, Boost.Python does not directly support everything you'll need
-when embedding. Therefore you'll need to use the
-[@http://www.python.org/doc/current/api/api.html Python/C API] to fill in
-the gaps. However, Boost.Python already makes embedding a lot easier and,
-in a future version, it may become unnecessary to touch the Python/C API at
-all. So stay tuned... :-)
-
-[h2 Building embedded programs]
-
-To be able to embed python into your programs, you have to link to
-both Boost.Python's as well as Python's own runtime library.
-
-Boost.Python's library comes in two variants. Both are located
-in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
-variants are called [^boost_python.lib] (for release builds) and
-[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
-you probably haven't built Boost.Python yet. See
-[@../../../building.html Building and Testing] on how to do this.
-
-Python's library can be found in the [^/libs] subdirectory of
-your Python directory. On Windows it is called pythonXY.lib where X.Y is
-your major Python version number.
-
-Additionally, Python's [^/include] subdirectory has to be added to your
-include path.
-
-In a Jamfile, all the above boils down to:
-
-[pre
-projectroot c:\projects\embedded_program ; # location of the program
-
-# bring in the rules for python
-SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
-include python.jam ;
-
-exe embedded_program # name of the executable
- : #sources
- embedded_program.cpp
- : # requirements
- boost_python c:\boost\libs\python
- $(PYTHON_PROPERTIES)
- $(PYTHON_LIB_PATH)
- $(PYTHON_EMBEDDED_LIBRARY) ;
-]
-
-[h2 Getting started]
-
-Being able to build is nice, but there is nothing to build yet. Embedding
-the Python interpreter into one of your C++ programs requires these 4
-steps:
-
-# '''#include''' [^]
-
-# Call Py_Initialize() to start the interpreter and create the [^__main__] module.
-
-# Call other Python C API routines to use the interpreter.
-
-[/ # Call Py_Finalize() to stop the interpreter and release its resources.]
-
-[note [*Note that at this time you must not call Py_Finalize() to stop the
-interpreter. This may be fixed in a future version of boost.python.]
-]
-
-(Of course, there can be other C++ code between all of these steps.)
-
-[:['[*Now that we can embed the interpreter in our programs, lets see how to put it to use...]]]
-
-[section Using the interpreter]
-
-As you probably already know, objects in Python are reference-counted.
-Naturally, the [^PyObject]s of the Python C API are also reference-counted.
-There is a difference however. While the reference-counting is fully
-automatic in Python, the Python C API requires you to do it
-[@http://www.python.org/doc/current/c-api/refcounting.html by hand]. This is
-messy and especially hard to get right in the presence of C++ exceptions.
-Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
-[@../../../v2/object.html object] class templates to automate the process.
-
-[h2 Running Python code]
-
-Boost.python provides three related functions to run Python code from C++.
-
- object eval(str expression, object globals = object(), object locals = object())
- object exec(str code, object globals = object(), object locals = object())
- object exec_file(str filename, object globals = object(), object locals = object())
-
-eval evaluates the given expression and returns the resulting value.
-exec executes the given code (typically a set of statements) returning the result,
-and exec_file executes the code contained in the given file.
-
-The [^globals] and [^locals] parameters are Python dictionaries
-containing the globals and locals of the context in which to run the code.
-For most intents and purposes you can use the namespace dictionary of the
-[^__main__] module for both parameters.
-
-Boost.python provides a function to import a module:
-
- object import(str name)
-
-import imports a python module (potentially loading it into the running process
-first), and returns it.
-
-Let's import the [^__main__] module and run some Python code in its namespace:
-
- object main_module = import("__main__");
- object main_namespace = main_module.attr("__dict__");
-
- object ignored = exec("hello = file('hello.txt', 'w')\n"
- "hello.write('Hello world!')\n"
- "hello.close()",
- main_namespace);
-
-This should create a file called 'hello.txt' in the current directory
-containing a phrase that is well-known in programming circles.
-
-[h2 Manipulating Python objects]
-
-Often we'd like to have a class to manipulate Python objects.
-But we have already seen such a class above, and in the
-[@python/object.html previous section]: the aptly named [^object] class
-and its derivatives. We've already seen that they can be constructed from
-a [^handle]. The following examples should further illustrate this fact:
-
- object main_module = import("__main__");
- object main_namespace = main_module.attr("__dict__");
- object ignored = exec("result = 5 ** 2", main_namespace);
- int five_squared = extract(main_namespace["result"]);
-
-Here we create a dictionary object for the [^__main__] module's namespace.
-Then we assign 5 squared to the result variable and read this variable from
-the dictionary. Another way to achieve the same result is to use eval instead,
-which returns the result directly:
-
- object result = eval("5 ** 2");
- int five_squared = extract(result);
-
-[h2 Exception handling]
-
-If an exception occurs in the evaluation of the python expression,
-[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown:
-
- try
- {
- object result = eval("5/0");
- // execution will never get here:
- int five_divided_by_zero = extract(result);
- }
- catch(error_already_set const &)
- {
- // handle the exception in some way
- }
-
-The [^error_already_set] exception class doesn't carry any information in itself.
-To find out more about the Python exception that occurred, you need to use the
-[@http://www.python.org/doc/api/exceptionHandling.html exception handling functions]
-of the Python C API in your catch-statement. This can be as simple as calling
-[@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to
-print the exception's traceback to the console, or comparing the type of the
-exception with those of the [@http://www.python.org/doc/api/standardExceptions.html
-standard exceptions]:
-
- catch(error_already_set const &)
- {
- if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
- {
- // handle ZeroDivisionError specially
- }
- else
- {
- // print all other errors to stderr
- PyErr_Print();
- }
- }
-
-(To retrieve even more information from the exception you can use some of the other
-exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
-
-[endsect]
-[endsect] [/ Embedding]
-
-[section Iterators]
-
-In C++, and STL in particular, we see iterators everywhere. Python also has
-iterators, but these are two very different beasts.
-
-[*C++ iterators:]
-
-* C++ has 5 type categories (random-access, bidirectional, forward, input, output)
-* There are 2 Operation categories: reposition, access
-* A pair of iterators is needed to represent a (first/last) range.
-
-[*Python Iterators:]
-
-* 1 category (forward)
-* 1 operation category (next())
-* Raises StopIteration exception at end
-
-The typical Python iteration protocol: [^[*for y in x...]] is as follows:
-
-[python]
-
- iter = x.__iter__() # get iterator
- try:
- while 1:
- y = iter.next() # get each item
- ... # process y
- except StopIteration: pass # iterator exhausted
-
-Boost.Python provides some mechanisms to make C++ iterators play along
-nicely as Python iterators. What we need to do is to produce
-appropriate `__iter__` function from C++ iterators that is compatible
-with the Python iteration protocol. For example:
-
-[c++]
-
- object get_iterator = iterator >();
- object iter = get_iterator(v);
- object first = iter.next();
-
-Or for use in class_<>:
-
- .def("__iter__", iterator >())
-
-[*range]
-
-We can create a Python savvy iterator using the range function:
-
-* range(start, finish)
-* range(start, finish)
-
-Here, start/finish may be one of:
-
-* member data pointers
-* member function pointers
-* adaptable function object (use Target parameter)
-
-[*iterator]
-
-* iterator()
-
-Given a container [^T], iterator is a shortcut that simply calls [^range]
-with &T::begin, &T::end.
-
-Let's put this into action... Here's an example from some hypothetical
-bogon Particle accelerator code:
-
-[python]
-
- f = Field()
- for x in f.pions:
- smash(x)
- for y in f.bogons:
- count(y)
-
-Now, our C++ Wrapper:
-
-[c++]
-
- class_("Field")
- .property("pions", range(&F::p_begin, &F::p_end))
- .property("bogons", range(&F::b_begin, &F::b_end));
-
-[*stl_input_iterator]
-
-So far, we have seen how to expose C++ iterators and ranges to Python.
-Sometimes we wish to go the other way, though: we'd like to pass a
-Python sequence to an STL algorithm or use it to initialize an STL
-container. We need to make a Python iterator look like an STL iterator.
-For that, we use `stl_input_iterator<>`. Consider how we might
-implement a function that exposes `std::list::assign()` to
-Python:
-
-[c++]
-
- template
- void list_assign(std::list& l, object o) {
- // Turn a Python sequence into an STL input range
- stl_input_iterator begin(o), end;
- l.assign(begin, end);
- }
-
- // Part of the wrapper for list
- class_ >("list_int")
- .def("assign", &list_assign)
- // ...
- ;
-
-Now in Python, we can assign any integer sequence to `list_int` objects:
-
-[python]
-
- x = list_int();
- x.assign([1,2,3,4,5])
-
-[endsect]
-[section:exception Exception Translation]
-
-All C++ exceptions must be caught at the boundary with Python code. This
-boundary is the point where C++ meets Python. Boost.Python provides a
-default exception handler that translates selected standard exceptions,
-then gives up:
-
- raise RuntimeError, 'unidentifiable C++ Exception'
-
-Users may provide custom translation. Here's an example:
-
- struct PodBayDoorException;
- void translator(PodBayDoorException const& x) {
- PyErr_SetString(PyExc_UserWarning, "I'm sorry Dave...");
- }
- BOOST_PYTHON_MODULE(kubrick) {
- register_exception_translator<
- PodBayDoorException>(translator);
- ...
-
-[endsect]
-[section:techniques General Techniques]
-
-Here are presented some useful techniques that you can use while wrapping code with Boost.Python.
-
-[section Creating Packages]
-
-A Python package is a collection of modules that provide to the user a certain
-functionality. If you're not familiar on how to create packages, a good
-introduction to them is provided in the
-[@http://www.python.org/doc/current/tut/node8.html Python Tutorial].
-
-But we are wrapping C++ code, using Boost.Python. How can we provide a nice
-package interface to our users? To better explain some concepts, let's work
-with an example.
-
-We have a C++ library that works with sounds: reading and writing various
-formats, applying filters to the sound data, etc. It is named (conveniently)
-[^sounds]. Our library already has a neat C++ namespace hierarchy, like so:
-
- sounds::core
- sounds::io
- sounds::filters
-
-We would like to present this same hierarchy to the Python user, allowing him
-to write code like this:
-
- import sounds.filters
- sounds.filters.echo(...) # echo is a C++ function
-
-The first step is to write the wrapping code. We have to export each module
-separately with Boost.Python, like this:
-
- /* file core.cpp */
- BOOST_PYTHON_MODULE(core)
- {
- /* export everything in the sounds::core namespace */
- ...
- }
-
- /* file io.cpp */
- BOOST_PYTHON_MODULE(io)
- {
- /* export everything in the sounds::io namespace */
- ...
- }
-
- /* file filters.cpp */
- BOOST_PYTHON_MODULE(filters)
- {
- /* export everything in the sounds::filters namespace */
- ...
- }
-
-Compiling these files will generate the following Python extensions:
-[^core.pyd], [^io.pyd] and [^filters.pyd].
-
-[note The extension [^.pyd] is used for python extension modules, which
-are just shared libraries. Using the default for your system, like [^.so] for
-Unix and [^.dll] for Windows, works just as well.]
-
-Now, we create this directory structure for our Python package:
-
-[pre
-sounds/
- \_\_init\_\_.py
- core.pyd
- filters.pyd
- io.pyd
-]
-
-The file [^\_\_init\_\_.py] is what tells Python that the directory [^sounds/] is
-actually a Python package. It can be a empty file, but can also perform some
-magic, that will be shown later.
-
-Now our package is ready. All the user has to do is put [^sounds] into his
-[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH]
-and fire up the interpreter:
-
-[python]
-
- >>> import sounds.io
- >>> import sounds.filters
- >>> sound = sounds.io.open('file.mp3')
- >>> new_sound = sounds.filters.echo(sound, 1.0)
-
-Nice heh?
-
-This is the simplest way to create hierarchies of packages, but it is not very
-flexible. What if we want to add a ['pure] Python function to the filters
-package, for instance, one that applies 3 filters in a sound object at once?
-Sure, you can do this in C++ and export it, but why not do so in Python? You
-don't have to recompile the extension modules, plus it will be easier to write
-it.
-
-If we want this flexibility, we will have to complicate our package hierarchy a
-little. First, we will have to change the name of the extension modules:
-
-[c++]
-
- /* file core.cpp */
- BOOST_PYTHON_MODULE(_core)
- {
- ...
- /* export everything in the sounds::core namespace */
- }
-
-Note that we added an underscore to the module name. The filename will have to
-be changed to [^_core.pyd] as well, and we do the same to the other extension modules.
-Now, we change our package hierarchy like so:
-
-[pre
-sounds/
- \_\_init\_\_.py
- core/
- \_\_init\_\_.py
- _core.pyd
- filters/
- \_\_init\_\_.py
- _filters.pyd
- io/
- \_\_init\_\_.py
- _io.pyd
-]
-
-Note that we created a directory for each extension module, and added a
-\_\_init\_\_.py to each one. But if we leave it that way, the user will have to
-access the functions in the core module with this syntax:
-
-[python]
-
- >>> import sounds.core._core
- >>> sounds.core._core.foo(...)
-
-which is not what we want. But here enters the [^\_\_init\_\_.py] magic: everything
-that is brought to the [^\_\_init\_\_.py] namespace can be accessed directly by the
-user. So, all we have to do is bring the entire namespace from [^_core.pyd]
-to [^core/\_\_init\_\_.py]. So add this line of code to [^sounds/core/\_\_init\_\_.py]:
-
- from _core import *
-
-We do the same for the other packages. Now the user accesses the functions and
-classes in the extension modules like before:
-
- >>> import sounds.filters
- >>> sounds.filters.echo(...)
-
-with the additional benefit that we can easily add pure Python functions to
-any module, in a way that the user can't tell the difference between a C++
-function and a Python function. Let's add a ['pure] Python function,
-[^echo_noise], to the [^filters] package. This function applies both the
-[^echo] and [^noise] filters in sequence in the given [^sound] object. We
-create a file named [^sounds/filters/echo_noise.py] and code our function:
-
- import _filters
- def echo_noise(sound):
- s = _filters.echo(sound)
- s = _filters.noise(sound)
- return s
-
-Next, we add this line to [^sounds/filters/\_\_init\_\_.py]:
-
- from echo_noise import echo_noise
-
-And that's it. The user now accesses this function like any other function
-from the [^filters] package:
-
- >>> import sounds.filters
- >>> sounds.filters.echo_noise(...)
-
-[endsect]
-[section Extending Wrapped Objects in Python]
-
-Thanks to Python's flexibility, you can easily add new methods to a class,
-even after it was already created:
-
- >>> class C(object): pass
- >>>
- >>> # a regular function
- >>> def C_str(self): return 'A C instance!'
- >>>
- >>> # now we turn it in a member function
- >>> C.__str__ = C_str
- >>>
- >>> c = C()
- >>> print c
- A C instance!
- >>> C_str(c)
- A C instance!
-
-Yes, Python rox. :-)
-
-We can do the same with classes that were wrapped with Boost.Python. Suppose
-we have a class [^point] in C++:
-
-[c++]
-
- class point {...};
-
- BOOST_PYTHON_MODULE(_geom)
- {
- class_("point")...;
- }
-
-If we are using the technique from the previous session,
-[link python.creating_packages Creating Packages], we can code directly
-into [^geom/\_\_init\_\_.py]:
-
-[python]
-
- from _geom import *
-
- # a regular function
- def point_str(self):
- return str((self.x, self.y))
-
- # now we turn it into a member function
- point.__str__ = point_str
-
-[*All] point instances created from C++ will also have this member function!
-This technique has several advantages:
-
-* Cut down compile times to zero for these additional functions
-* Reduce the memory footprint to virtually zero
-* Minimize the need to recompile
-* Rapid prototyping (you can move the code to C++ if required without changing the interface)
-
-You can even add a little syntactic sugar with the use of metaclasses. Let's
-create a special metaclass that "injects" methods in other classes.
-
- # The one Boost.Python uses for all wrapped classes.
- # You can use here any class exported by Boost instead of "point"
- BoostPythonMetaclass = point.__class__
-
- class injector(object):
- class __metaclass__(BoostPythonMetaclass):
- def __init__(self, name, bases, dict):
- for b in bases:
- if type(b) not in (self, type):
- for k,v in dict.items():
- setattr(b,k,v)
- return type.__init__(self, name, bases, dict)
-
- # inject some methods in the point foo
- class more_point(injector, point):
- def __repr__(self):
- return 'Point(x=%s, y=%s)' % (self.x, self.y)
- def foo(self):
- print 'foo!'
-
-Now let's see how it got:
-
- >>> print point()
- Point(x=10, y=10)
- >>> point().foo()
- foo!
-
-Another useful idea is to replace constructors with factory functions:
-
- _point = point
-
- def point(x=0, y=0):
- return _point(x, y)
-
-In this simple case there is not much gained, but for constructurs with
-many overloads and/or arguments this is often a great simplification, again
-with virtually zero memory footprint and zero compile-time overhead for
-the keyword support.
-
-[endsect]
-[section Reducing Compiling Time]
-
-If you have ever exported a lot of classes, you know that it takes quite a good
-time to compile the Boost.Python wrappers. Plus the memory consumption can
-easily become too high. If this is causing you problems, you can split the
-class_ definitions in multiple files:
-
-[c++]
-
- /* file point.cpp */
- #include
- #include
-
- void export_point()
- {
- class_("point")...;
- }
-
- /* file triangle.cpp */
- #include
- #include
-
- void export_triangle()
- {
- class_("triangle")...;
- }
-
-Now you create a file [^main.cpp], which contains the [^BOOST_PYTHON_MODULE]
-macro, and call the various export functions inside it.
-
- void export_point();
- void export_triangle();
-
- BOOST_PYTHON_MODULE(_geom)
- {
- export_point();
- export_triangle();
- }
-
-Compiling and linking together all this files produces the same result as the
-usual approach:
-
- #include
- #include
- #include
-
- BOOST_PYTHON_MODULE(_geom)
- {
- class_("point")...;
- class_("triangle")...;
- }
-
-but the memory is kept under control.
-
-This method is recommended too if you are developing the C++ library and
-exporting it to Python at the same time: changes in a class will only demand
-the compilation of a single cpp, instead of the entire wrapper code.
-
-[note If you're exporting your classes with [@../../../../pyste/index.html Pyste],
-take a look at the [^--multiple] option, that generates the wrappers in
-various files as demonstrated here.]
-
-[note This method is useful too if you are getting the error message
-['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
-a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].]
-
-[endsect]
-[endsect] [/ General Techniques]
-
-
diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html
deleted file mode 100644
index 79242777..00000000
--- a/doc/tutorial/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
- Automatic redirection failed, click this
- link
-
-
-April was a short month as far as Boost.Python was concerned, since
-the spring ISO C++ Committee Meeting (and associated vacation)
-occupied me for the 2nd half of the month. However, a suprising amount
-of work got done...
-
-
-
-I began using the Boost.Preprocessor
-metaprogramming library to generate support for functions and member
-functions of arbitrary arity, which was, to say the least, quite an
-adventure. The feedback cycle resulting from my foray into
-Boost.Preprocessor resulted in several improvements to the library,
-most notably in its documentation.
-
-
-
-Boost.Python now supports calls of up to 17 arguments on most
-compilers. Because most EDG-based compilers have dismal preprocessor
-performance, I had to "manually" expand the metaprograms for
-arities from zero to fifteen arguments, and EDG-based compilers with
-__EDG_VERSION__ <= 245 only support 15
-arguments by default. If some crazy program finds a need for more than
-the default arity support, users can increase the base support by
-setting the BOOST_PYTHON_MAX_ARITY preprocessor symbol.
-
-
-
-I mentioned in last month's report that I
-wasn't pleased with the interface for the interface for calling into
-Python, so now it has been redesigned. The new interface is outlined
-in this
-message (though the GCC 2.95.3 bugs have been fixed).
-
-
-
-At least two people outside of Kull began actually using Boost.Python
-v2 in earnest this month. Peter Bienstman and Pearu Pearson both
-provided valuable real-world bug reports that helped me to improve the
-library's robustness.
-
-
-
-Answering some of Pearu's questions about explicitly converting
-objects between Python and C++ actually led me to a new understanding
-of the role of the current conversion facilities. In Boost.Python v1,
-all conversions between Python and C++ were handled by a single family
-of functions, called to_python() and
-from_python(). Since the primary role of Boost.Python is
-to wrap C++ functions in Python, I used these names for the first kind
-of converters I needed: those that extract C++ objects to be used as
-function arguments and which C++ function return values to
-Python. The better-considered approach in Boost.Python v2 uses a
-completely different mechanism for conversions used when calling
-Python from C++, as in wrapped virtual function implementations. I
-usually think of this as a "callback", as in "calling
-back into Python", and I named the converters used in callbacks
-accordingly: to_python_callback and
-from_python_callback. However, as it turns out, the
-behavior of the "callback" converters is the appropriate one
-for users who want to explicitly extract a C++ value from a Python
-object, or create a Python object from a C++ value. The upshot is that
-it probably makes sense to change the name of the existing to_python and
-from_python so those names are available for the
-user-friendly explicit converters.
-
-
-Another
-of Pearu's questions pushes momentum further in the direction of a
-more-sophisticated overloading mechanism than the current
-simple-minded "first match" approach, as I suggested last month.
-
-
-
-As much as I'm looking forward to retiring Boost.Python v1, a
-significant amount of effort has been being spent dealing with support
-problems; the saying that code rots when left alone is true, and
-Boost.Python is no exception. Eventually it became obvious to me that
-we were going to have to invest some effort in keeping V1 healthy
-while working on V2. Ralf and I have expanded support for various
-compilers and stabilized the V1 codebase considerably. We discarded
-the obsolete Visual Studio projects which were causing so much
-confusion. Still to do before the next Boost release:
-
-
Update the build/test documentation with detailed instructions for
-configuring various toolsets.
-
Provide some links to Boost.Python v2 to let people know what's
-coming.
-
Models of the CallPolicies concept are used to specialize the behavior
- of Python callable objects generated by Boost.Python to wrapped C++
- objects like function and member function pointers, providing three
- behaviors:
-
-
-
precall - Python argument tuple management before the
- wrapped object is invoked
-
-
result_converter - C++ return value handling
-
-
postcall - Python argument tuple and result management
- after the wrapped object is invoked
-
extract_return_type - metafunction for extracting the return type from a given signature type sequence
-
-
-
CallPolicies Composition
- In order to allow the use of multiple models of CallPolicies in the same
- callable object, Boost.Python's CallPolicies class templates provide a
- chaining interface which allows them to be recursively composed. This
- interface takes the form of an optional template parameter,
- Base which defaults to default_call_policies.
- By convention, the precall function of the Base
- is invoked after the precall function supplied by the
- outer template, and the postcall function of the
- Base is invoked before the postcall
- function of the outer template. If a result_converter is
- supplied by the outer template, it replaces any
- result_converter supplied by the Base. For an
- example, see return_internal_reference.
-
-
-
Concept Requirements
-
-
CallPolicies Concept
-
-
In the table below, x denotes an object whose type
- P is a model of CallPolicies, a
- denotes a PyObject* pointing to a Python argument tuple
- object, and r denotes a PyObject*
- referring to a "preliminary" result object.
-
-
-
-
Expression
-
-
Type
-
-
Result/Semantics
-
-
-
-
x.precall(a)
-
-
convertible to bool
-
-
returns false and PyErr_Occurred() != 0
- upon failure, true otherwise.
0 0 and PyErr_Occurred() != 0
- upon failure. Must "conserve references" even in the event of an
- exception. In other words, if r is not returned, its
- reference count must be decremented; if another existing object is
- returned, its reference count must be incremented.
Permission to copy, use, modify, sell and distribute this software is
- granted provided this copyright notice appears in all copies. This
- software is provided "as is" without express or implied warranty, and
- with no claim as to its suitability for any purpose.
Permission to copy, use, modify, sell
- and distribute this software is granted provided this copyright notice appears
- in all copies. This software is provided "as is" without express or implied
- warranty, and with no claim as to its suitability for any purpose.
-
-
diff --git a/doc/v2/Extractor.html b/doc/v2/Extractor.html
deleted file mode 100644
index 441ca38b..00000000
--- a/doc/v2/Extractor.html
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
An Extractor is a class which Boost.Python can use to extract C++
-objects from Python objects, and is typically used by facilities that
-define from_python conversions for
-"traditional" Python extension types.
-
-
Concept Requirements
-
Extractor Concept
-
-
In the table below, X denotes a model of
-Extractor and a denotes an instance of a Python
-object type.
-
-
-
-
-
Expression
-
Type
-
Semantics
-
-
-
-
X::execute(a)
-
non-void
-
Returns the C++ object being extracted. The
- execute function must not be overloaded.
-
Points to the ob_type field of an object which is
- layout-compatible with PyObject
-
-
-
-
-
-
-
Notes
-
-Informally, an Extractor's execute member must be a
-non-overloaded static function whose single argument is a Python
-object type. Acceptable Python object types include those publicly (and
-unambiguously) derived from PyObject, and POD types which
-are layout-compatible with PyObject.
-
-
-
Permission to copy, use, modify, sell
- and distribute this software is granted provided this copyright notice appears
- in all copies. This software is provided "as is" without express or implied
- warranty, and with no claim as to its suitability for any purpose.
-
-
diff --git a/doc/v2/HolderGenerator.html b/doc/v2/HolderGenerator.html
deleted file mode 100644
index 58b4265a..00000000
--- a/doc/v2/HolderGenerator.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
A HolderGenerator is a unary metafunction class which returns types
-suitable for holding instances of its argument in a wrapped C++ class
-instance.
-
-
Concept Requirements
-
HolderGenerator Concept
-
-
In the table below, G denotes an type which
-models HolderGenerator, and X denotes a class
-type.
-
-
-
-
-
Expression
-
Requirements
-
-
-
-
G::apply<X>::type
-
A concrete subclass of instance_holder
- which can hold objects of type X.
-
Permission to copy, use, modify, sell
- and distribute this software is granted provided this copyright notice appears
- in all copies. This software is provided "as is" without express or implied
- warranty, and with no claim as to its suitability for any purpose.
-
-
diff --git a/doc/v2/Jun2002.html b/doc/v2/Jun2002.html
deleted file mode 100644
index db1fc25c..00000000
--- a/doc/v2/Jun2002.html
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
-
-July was mostly focused on allowing expressive manipulation of
-individual Python objects, or what Ralf Grosse-Kunstleve calls
-"Writing Python in C++". The work began with this posting,
-which outlines the issues and intention.
-
-
-
-The most basic element needed was a replacement for the
-reference<> class template and the
-ref typedef from Boost.Python v1, a simple smart
-pointer to a Python object. The old v1 typedef
-"ref" (for
-reference<PyObject>) had to be retired because I
-thought it would be too confusing given the importance of boost::ref() to this
-library. I began a discussionof
-possible names, and it was eventually decided
-to rename reference to handle and supply a
-default argument so that ref could be spelled
-handle<> without an additional typedef. There
-were also some interface changes to make it safer and more-efficient
-to interface with the raw
-PyObject*s forced on us by Python's 'C' API. A
-discussion of those protocols can be found here.
-
-
-
-It is intended that users will seldom need or want to work with
-handle<>; its major distinguishing features are
-that it gives direct access to the underlying object representation
-through operator* and operator->, and
-that can be NULL, both sources of danger. Instead the
-library provides a class called object, which
-encapsulates a valid Python object and provides a similar interface to
-Python's.
-
-
-
-The first challenge was to provide support for object manipulations
-using a Python-like syntax, mostly in the form of operator overloads:
-
-
-
Python
C++
-
-
-
y = x.foo
y = x.attr("foo");
-
-
x.foo = 1
x.attr("foo") = 1;
-
-
-
y = x[z]
y = x[z];
-
-
x[z] = 1
x[z] = 1;
-
-
-
y = x[3:-1]
y = x.slice(3,-1);
-
-
-
y = x[3:]
y = x.slice(3,_);
-
-
-
y = x[:-2]
y = x.slice(_,-2);
-
-
-
z = x(1, y)
z = x(1, y);
-
-
z = x.f(1, y)
z = x.attr("f")(1, y);
-
-
-
not x
!x
-
-
-
x and y
x and y
-
-
-I'm still a unsatisfied with the interface for attribute access. There
-original proposal used a syntax like this one:
-
-y = x._("foo");
-x._("foo") = 1;
-
-
-which was only marginally better than what we've got. Niki Spahiev
-then pointed
-out a potential conflict with the macro which GNU Gettext suggests
-people define. This unfortunate state of affairs forced us into using
-attr instead. I'd still like to find a better interface,
-but the lack of overloadable C++ operators which aren't already used
-in Python is an obstacle. The comma operator is still a possibility,
-but it has the wrong precedence:
-
-
-The object class also provided an opportunity to replace
-Boost.Python v1's to_python() as a user-level
-interface. Instead, object has a templated constructor
-which can be used to convert any C++ object to Python using the same
-underlying mechanisms used for the arguments to call<>.
-
-
Incidentally, the implementation of operator and conversion support
-for object uncovered an inordinate number of compiler bugs in our
-targeted platforms. It was a lot more "interesting" than it
-should have been.
-
-
-
-With object implemented, it was time to begin replacing
-the ad-hoc implementations of list, string,
-and dictionary supplied by Boost.Python v1 with something
-more robust. I started with list as an example. Because
-object already provides all of the requisite operators,
-publicly deriving list from object seemed like a good
-choice. The remaining issues were what do do about the one-argument
-list constructor (which in Python attempts to convert its argument to
-a list), and how to deal converting with list arguments
-to wrapped functions. Some of the issues are laid out in this
-thread. Ultimately, it was decided that list(x)
-should do the same thing in C++ as in Python (conversion), while
-list arguments should only match Python
-lists (and list subclasses). The
-implementation worked well, and provided a roadmap
-for the protocol to be used for implementation of the other built-in
-types.
-
-
-
-Support for C++ long long and unsigned long
-long
-(and __int64 on MSVC) to/from python conversions was
-added this month. We also improved handling of numeric overflows when
-converting, e.g., a Python int to a type with a more limited range of
-representation.
-
-
-
-As I write this we are already well into the month of July, so I
-suggest you consult the Mailing
-List Archive if you want to know what's been happening. Otherwise
-you'll just have to wait till next month (hopefully the beginning).
-
-
-
-March was mostly devoted to the reimplementation of features from
-Boost.Python v1, and some new features. Re-examination of the features
-from Boost.Python v1 allowed me to make significant improvements.
-
-
-
-The ability to call Python from C++ is crucial for virtual function
-support. Implementing this feature well for V2 proved to be more
-interesting than I expected. You can review most of the relevant
-design decisions
-here.
-
-
-One point which isn't emphasized in that document is that there
-are subtle differences in the way from_python conversions
-work when used for C++ function arguments and Python function return
-values. In particular, while T const& arguments may
-invoke rvalue converters, a reference-to-const return value requires
-an lvalue converter, since a temporary conversion result would leave
-the returned reference dangling.
-
-
I'm not particularly pleased with the current callback interface,
-since it usually results in constructs like:
-
-return returning<X&>::call(f, obj);
-
-However, I think the following may be possible and I plan to investigate:
-
-return apply<X&>(f, obj);
-
-I'm open to suggestion for better names (and syntaxes)!
-
-
-
-Once Python callbacks were implemented, it was just a short step to
-implementing virtual functions. Python extension class exposing a C++
-class whose virtual functions are overridable in Python must actually
-hold a C++ instance of a class derived from the one exposed to
-Python. Needing some way for users to specify that class, I added an
-optional template argument to value_holder_generator and
-pointer_holder_generator<> to specify the class
-actually held. This move began to put pressure on the
-class_<> interface, since the need for the user to
-produce complicated instantations of
-class_<> was increased:
-
-
-
-Normally when a C++ class is exposed to Python, the library registers
-a conversion function which allows users to wrap functions returning
-values of that type. Naturally, these return values are temporaries,
-so the conversion function must make a copy in some
-dynamically-allocated storage (a "holder") which is managed
-by the corresponding Python object.
-
-
Unfortunately, in the case of abstract classes (and other types
-without a publicly-accessible copy constructor), instantiating this
-conversion function causes a compilation error. In order to support
-non-copyable classes, there had to be some way to prevent the library
-from trying to instantiate the conversion function. The only practical
-approach I could think of was to add an additional template parameter
-to the class_<> interface. When the number of
-template parameters with useful defaults begins to grow, it is often
-hard to choose an order which allows users to take advantage of the
-defaults.
-
-
-
-This was the straw that broke the
-class_<> interface's back and caused the redesign
-whose outcome is detailed here.
-The approach allows the user to supply the optional parameters in an
-arbitrary order. It was inspired by the use of named
-template parameters in the Boost Iterator Adaptor
-Library, though in this case it is possible to deduce the meaning
-of the template parameters entirely from their type properties,
-resulting in a simpler interface. Although the move from a
-policy-based design to what resembles a configuration DSL usually
-implies a loss of flexibility, in this case I think any costs are far
-outweighed by the advantages.
-
-
Note: working around the limitations of the various compilers I'm
-supporting was non-trivial, and resulted in a few messy implementation
-details. It might be a good idea to switch to a more-straightforward
-approach once Metrowerks CodeWarrior Pro8 is released.
-
-
-
-Support for C++ implicit conversion involves creating
-from_python converters for a type U which in
-turn use from_python converters registered for a type
-T where there exists a implicit conversion from
-T to U. The current implementation is
-subject to two inefficiencies:
-
-
-
Because an rvalue from_python converter produces two
-pieces of data (a function and a void*) from its
-convertible() function, we end up calling the function
-for T twice: once when the converter is looked up in the
-registry, and again when the conversion is actually performed.
-
-
A vector is used to mark the "visited" converters, preventing
-infinite recursion as T to
-U and U to T converters
-continually search through one-another.
-
-
-
-I consider the former to be a minor issue. The second may or may not
-prove to be computationally significant, but I believe that
-architecturally, it points toward a need for more sophisticated
-overload resolution. It may be that we want CLOS-style multimethod
-dispatching along with C++ style rules that prevent more than one
-implicit conversion per argument.
-
-
-
-To supply the ability to directly access data members, I was able to
-hijack the new Python property
-type. I had hoped that I would also be able to re-use the work of make_function to create callable python
-objects from C++ functions which access a data member of a given
-class. C++ facilities for specifying data member pointer non-type
-template arguments require the user to explicitly specify the type of
-the data member and this under-utilized feature is also not
-well-implemented on all compilers, so passing the member pointer as a
-runtime value is the only practical approach. The upshot is that any
-such entity would actually have to be a function object, and I
-haven't implemented automatic wrapping of C++ callable function
-objects yet, so there is less re-use in the implementation than I'd
-like. I hope to implement callable object wrapping and refactor this
-code one day. I also hope to implement static data member support,
-for which Python's property will not be an appropriate descriptor.
-
-
Implement a CallPolicy interface for constructors of wrapped
-classes
-
Implement conversions for char types.
-
Implement automated code generation for all headers containing
-families of overloaded functions to handle arbitrary arity.
-
-
-I also hope to implement a mechanism for generating conversions
-between arbitrary Python sequences and C++ containers, if time permits
-(and others haven't already done it)!
-
-
-
-The older version of KCC used by Kull is generating lots of warnings
-about a construct I use to instantiate static members of various class
-templates. I'm thinking of moving to an idiom which uses a function
-template to suppress it, but worry about bloating the size of debug
-builds. Since KCC users may be moving to GCC, I'm not sure that it's
-worth doing anything about it.
-
-
-
-Aside from library development, work on Boost.Python in May was
-focused on reducing the support burden. In recent weeks, responding to
-requests for support, espcially surrounding building the library, had
-begun to impede progress on development. There was a major push to
-release a stable 1.28.0 of Boost, including documentation of Boost.Build and specific
-instructions for building Boost.Python
-v1. The documentation for Boost.Python v2 was also updated as
-described here.
-
-
-
- The Kull group required the ability to build and test Boost.Python
- extensions on AIX, a platform with "creatively designed"
- shared library semantics. Making this work was a multi-pronged
- effort, involving changes to Boost.Build and some great research by
- Martin Casado which uncovered the key mechanism required to allow
- shared libraries to use functions from the Python executable. The
- current solution used in Boost.Build relies on a Python
- Script as part of the build process. This is not a problem for
- Boost.Python, as Python will be available. However, the commands
- issued by the script are so simple that a 100%-pure-Boost.Jam
- solution is surely possible. Linking on AIX is sufficiently
- interesting to have skewed the Boost.Python development schedule a
- bit.
-
-
-
-Support for exposing C++ operators and functions as the corresponding
-Python special methods was added. Thinking that the Boost.Python
-v1 interface was a little too esoteric (especially the use of
-left_operand<...>/right_operand<...> for
-asymmetric operands), I introduced a simple form of expression
-templates which allow users to simply write the expressions that
-should be wrapped, as in this example.
-
-
-
-The Kull iteration interfaces also required the ability to iterate
-over a sequence specified by an instance's attribute:
-
->>> f = field()
->>> for e in f.elements:
-... print e,
-
-
-This forced the exposure of the property
- interface used internally to implement the data member exposure
- facility described in March. Properties are an
- incredibly useful idiom, so it's good to be able to provide them
- at little new development cost.
-
-
-
-Ralf Grosse-Kunstleve has been working on pickling support for v2. To
-make it work correctly, he had to make sure that a class'
-__module__ attribute was set correctly.
-
-
-
-The new back_reference<T> template can be used as a
-function parameter when the user needs access to both a T
-argument and to the Python object which manages it. The function will
-only match in the overload resolution process if it would match the
-same function signature with T substituted for
-back_reference<T>. This feature is not yet
-documented.
-
-
-
- As usual, careful documentation forces one to consider the
- interface again, and there were many interface changes
- associated with this effort, including the elevation of the
- following components from implementation detail to
- first-class library citizen:
-
-
-
-It appears that the world of C++ <==> Python conversion rules is
-an endlessly-rich area of exploration. Completing the conversions for
-char and char const* types, as described at
-the end of April's report,
-uncovered some interesting new shades to the problem. It turns out to
-be worth distinguishing mutable and immutable lvalue conversions,
-because despite the fact that Python doesn't understand
-const, it does understand immutability (c.f. Python
-strings, which expose an immutable char pointer). It is
-also worth recognizing types which represent lvalue sequences,
-to prevent Python "foobar" from being silently
-truncated to C++ 'f'. More details on this insight can be
-found in the mailing list
-archive. I don't plan to do anything about this immediately, but I
-do think it's the right direction to go in the long run.
-
-
-
-In order to better coordinate changes made by multiple developers, I
-enabled syncmail
-for the Boost.Python CVS trees, and established an associated mailing
-list. Subscribe to this list to receive notices of each new
-checkin.
-
-
-
-Beyond the vagaries of dynamic linking on AIX, I have been
-participating in a more-general discussion of dynamic linking for
-C++. Needless to say, C++ dynamic linking is of critical importance to
-Boost.Python: all extension modules are normally built as shared
-libraries, and Boost.Python extension modules share a common library
-as well.
-
-In fact, there are at least two separate conversations. One
-in the C++ standard extensions mailing list concerns what can be
-standardized for C++ and shared libraries; the other, mostly on the gcc mailing list, concerns the
-behavior of GCC on Posix/ELF platforms.
-
-Some of the GCC threads are here:
-
-
-
-Development is focused on what's needed to be able to retire
-Boost.Python v1. At the moment, that means deciding the user-friendly
-interfaces for to_/from_python conversion, and formally exposing the
-Python object smart pointers and object wrapper classes. Quite a few
-questions have also been showing up recently about how to embed Python
-with Boost.Python, and how to link with it statically; the solutions
-to these issues will probably have to be formalized before long.
-
-
This page defines two concepts used to describe classes which manage a
- Python objects, and which are intended to support usage with a
- Python-like syntax.
-
-
Concept Requirements
-
-
ObjectWrapper Concept
- Models of the ObjectWrapper concept have object as a publicly-accessible base class,
- and are used to supply special construction behavior and/or additional
- convenient functionality through (often templated) member functions.
- Except when the return type R is itself an TypeWrapper, a member function invocation of
- the form
-
- TypeWrapper is a refinement of ObjectWrapper which is associated with a
- particular Python type X. For a given TypeWrapper
- T, a valid constructor expression
-
-T(a1, a2,...an)
-
- builds a new T object managing the result of invoking
- X with arguments corresponding to
-
-
-When used as arguments to wrapped C++ functions, or as the template
-parameter to extract<>, only
-instances of the associated Python type will be considered a match.
-
-
- The upshot of the special member function invocation rules when the
- return type is a TypeWrapper is that it is possible for the returned
- object to manage a Python object of an inappropriate type. This is not
- usually a serious problem; the worst-case result is that errors will be
- detected at runtime a little later than they might otherwise be. For an
- example of how this can occur, note that the dict member function items
- returns an object of type list. Now suppose the user defines this
- dict subclass in Python:
-
->>> class mydict(dict):
-... def items(self):
-... return tuple(dict.items(self)) # return a tuple
-
- Since an instance of mydict is also an instance of
- dict, when used as an argument to a wrapped C++ function,
- boost::python::dict can
- accept objects of Python type mydict. Invoking
- items() on this object can result in an instance of boost::python::list which actually
- holds a Python tuple. Subsequent attempts to use list methods (e.g.
- append, or any other mutating operation) on this object will
- raise the same exception that would occur if you tried to do it from
- Python.
-
-
-
A ResultConverter for a type T is a type whose
-instances can be used to convert C++ return values of type
-Tto_python. A ResultConverterGenerator is
-an MPL unary metafunction class which, given the return type of a C++
-function, returns a ResultConverter for that type. ResultConverters in
-Boost.Python generally inspect library's registry of converters to
-find a suitable converter, but converters which don't use the registry
-are also possible.
-
-
Concept Requirements
-
ResultConverter Concept
-
-
In the table below, C denotes a ResultConverter
-type for a type R , c denotes
-an object of type C , and r
-denotes an object of type R.
-
-
-
-
-
Expression
-
Type
-
Semantics
-
-
-
-
C c;
-
-
Constructs a C object.
-
-
-
-
c.convertible()
-
convertible to bool
-
false iff no conversion from any R value
- to a Python object is possible.
-
-
-
-
c(r)
-
convertible to PyObject*
-
A pointer to a Python object corresponding to r,
- or 0 iff r could not be converted
- to_python, in which case PyErr_Occurred
- should return non-zero.
-
-
-
c.get_pytype()
-
PyTypeObject const*
-
A pointer to a Python Type object corresponding to result of the conversion,
- or 0. Used for documentation generation. If 0 is returned
- the generated type in the documentation will be object .
-
-
-
-
ResultConverterGenerator Concept
-
In the table below, G denotes a
-ResultConverterGenerator type and R denotes a possible
-C++ function return type.
-
-
Permission to copy, use, modify, sell
- and distribute this software is granted provided this copyright notice appears
- in all copies. This software is provided "as is" without express or implied
- warranty, and with no claim as to its suitability for any purpose.
-
-
diff --git a/doc/v2/acknowledgments.html b/doc/v2/acknowledgments.html
deleted file mode 100644
index 28f1b1db..00000000
--- a/doc/v2/acknowledgments.html
+++ /dev/null
@@ -1,135 +0,0 @@
-
-
-
-
-
-
-
Dave Abrahams is
- the architect, designer, and implementor of Boost.Python.
-
-
Brett Calcott
- contributed and maintains the Visual Studio project files and
- documentation.
-
-
Gottfried
- Ganauge supplied support for opaque pointer conversions,
- complete with documentation and a regression test (and I didn't
- even have to ask him for those)!
-
-
Ralf W.
- Grosse-Kunstleve implemented the pickle
- support, and has enthusiastically supported the library since its
- birth, contributing to design decisions and providing invaluable
- real-world insight into user requirements. Ralf has written some extensions for converting C++ containers that I
- hope will be incorporated into the library soon. He also implemented the
- cross-module support in the first version of Boost.Python. More
- importantly, Ralf makes sure nobody forgets the near-perfect synergy of
- C++ and Python for solving the problems of large-scale software
- construction.
-
-
Aleksey Gurtovoy
- wrote an incredible C++ Template
- Metaprogramming Library which allows Boost.Python to perform much of
- its compile-time magic. In addition, Aleksey very generously contributed
- his time and deep knowledge of the quirks of various buggy compilers to
- help us get around problems at crucial moments.
-
-
Paul Mensonides,
- building on the work Vesa
- Karvonen, wrote a similarly amazing Preprocessor Metaprogramming
- Library, and generously contributed the time and expertise to get it
- working in the Boost.Python library, rewriting much of Boost.Python to
- use the new preproccessor metaprogramming constructs and helping us to
- work around buggy and slow C++ preprocessors.
Martin Casado solved some sticky problems which allow us to build the
- Boost.Python shared library for AIX's crazy dynamic linking model.
-
-
Achim Domma contributed some
- of the Object Wrappers and
- HTML templates for this documentation. Dave Hawkes contributed
- inspiration for the use of the scope class to simplify module
- definition syntax. Pearu Pearson wrote some of the test cases that are in
- the current test suite.
Ullrich
- Koethe had independently developed a similar system. When he
- discovered Boost.Python v1, he generously contributed countless hours of
- coding and much insight into improving it. He is responsible for an early
- version of the support for function overloading and wrote the support for
- reflecting C++ inheritance relationships. He has helped to improve
- error-reporting from both Python and C++ (we hope to do as well in v2
- again soon), and has designed the original support for exposing numeric
- operators, including a way to avoid explicit coercion by means of
- overloading.
-
-
The members of the boost mailing list and the Python community
- supplied invaluable early feedback. In particular, Ron Clarke, Mark
- Evans, Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott
- took the brave step of trying to use Boost.Python while it was still in
- early stages of development.
-
-
The first version of Boost.Python would not have been possible without
- the support of Dragon Systems, which supported its development and
- release as a Boost library.
Supplies a family of overloaded functions for specifying argument
- keywords for wrapped C++ functions.
-
-
keyword-expressions
-
-
A keyword-expression results in an object which holds a
- sequence of ntbses, and whose type
- encodes the number of keywords specified. The keyword-expression
- may contain default values for some or all of the keywords it holds
-
-
Classes
-
-
class arg;
-
-
The objects of class arg are keyword-expressions holding one keyword (
- size one )
Requires:R is a pointer type, reference
- type, or a complete type with an accessible copy constructor
-
-
Effects: Invokes callable(a1, a2, ...an) in
- Python, where a1...an are the arguments to
- call(), converted to Python objects.
-
Returns: The result of the Python call, converted to the C++ type R.
-
-
-
Rationale: For a complete semantic description and
- rationale, see this page.
-
-
-
-
Example(s)
-
-The following C++ function applies a Python callable object to its two
-arguments and returns the result. If a Python exception is raised or
-the result can't be converted to a double, an exception
-is thrown.
-
-
<boost/python/call_method.hpp> defines the call_method family of overloaded
- function templates, used to invoke callable attributes of Python objects
- from C++.
Requires:R is a pointer type, reference type,
- or a complete type with an accessible copy constructor
-
-
Effects: Invokes
- self.method(a1, a2, ...an) in
- Python, where a1...an are the
- arguments to call_method(), converted to Python objects.
- For a complete semantic description, see this
- page.
-
-
Returns: The result of the Python call, converted to the C++
- type R.
-
-
Rationale:call_method is critical to
- implementing C++ virtual functions which are overridable in Python, as
- shown by the example below.
-
-
-
Example(s)
- The following C++ illustrates the use of call_method in
- wrapping a class with a virtual function that can be overridden in
- Python:
-
-
- The simplest way to call a Python function from C++, given an object instance f
- holding the function, is simply to invoke its function call operator.
-
-f("tea", 4, 2) // In Python: f('tea', 4, 2)
-
- And of course, a method of an object instance x can
- be invoked by using the function-call operator of the corresponding
- attribute:
-
-x.attr("tea")(4, 2); // In Python: x.tea(4, 2)
-
-
-
If you don't have an object instance, Boost.Python
- provides two families of function templates, call and call_method, for invoking
- Python functions and methods respectively on PyObject*s. The
- interface for calling a Python function object (or any Python callable
- object) looks like:
Arguments are converted to Python according to their type. By default,
- the arguments a1...aN are copied into
- new Python objects, but this behavior can be overridden by the use of
- ptr() and ref():
-
-class X : boost::noncopyable
-{
- ...
-};
-
-void apply(PyObject* callable, X& x)
-{
- // Invoke callable, passing a Python object which holds a reference to x
- boost::python::call<void>(callable, boost::ref(x));
-}
-
- In the table below, x denotes the actual argument
- object and cv denotes an optional
- cv-qualification: "const", "volatile",
- or "const volatile".
-
-
-
-
Argument Type
-
-
Behavior
-
-
-
-
T cv&
- T cv
-
-
The Python argument is created by the same means used for the
- return value of a wrapped C++ function returning T. When
- T is a class type, that normally means *x
- is copy-constructed into the new Python object.
-
-
-
-
T*
-
-
If x == 0, the Python argument will be
- None.
- Otherwise, the Python argument is created by the same means used for
- the return value of a wrapped C++ function returning T.
- When T is a class type, that normally means
- *x is copy-constructed into the new Python object.
The Python argument contains a pointer to, rather than a copy of,
- x.get(). Note: failure to ensure that no Python code
- holds a reference to the resulting object beyond the lifetime of
- *x.get()may result in a crash!
If x.get() == 0, the Python argument will
- be None.
- Otherwise, the Python argument contains a pointer to, rather than a
- copy of, *x.get(). Note: failure to ensure that no
- Python code holds a reference to the resulting object beyond the
- lifetime of *x.get()may result in a crash!
- In general, call<ResultType>() and
- call_method<ResultType>() return
- ResultType by exploiting all lvalue and rvalue
- from_python converters registered for ResultType and
- returning a copy of the result. However, when ResultType is
- a pointer or reference type, Boost.Python searches only for lvalue
- converters. To prevent dangling pointers and references, an exception
- will be thrown if the Python result object has only a single reference
- count.
-
-
- In general, to get Python arguments corresponding to
- a1...aN, a new Python object must be
- created for each one; should the C++ object be copied into that Python
- object, or should the Python object simply hold a reference/pointer to
- the C++ object? In general, the latter approach is unsafe, since the
- called function may store a reference to the Python object somewhere. If
- the Python object is used after the C++ object is destroyed, we'll crash
- Python.
-
-
In keeping with the philosophy that users on the Python side shouldn't
- have to worry about crashing the interpreter, the default behavior is to
- copy the C++ object, and to allow a non-copying behavior only if the user
- writes boost::ref(a1)
- instead of a1 directly. At least this way, the user doesn't get dangerous
- behavior "by accident". It's also worth noting that the non-copying
- ("by-reference") behavior is in general only available for class types,
- and will fail at runtime with a Python exception if used otherwise[1].
-
-
However, pointer types present a problem: one approach is to refuse to
- compile if any aN has pointer type: after all, a user can always pass
- *aN to pass "by-value" or ref(*aN) to indicate
- a pass-by-reference behavior. However, this creates a problem for the
- expected null pointer to None conversion: it's illegal to
- dereference a null pointer value.
-
-
The compromise I've settled on is this:
-
-
-
The default behavior is pass-by-value. If you pass a non-null
- pointer, the pointee is copied into a new Python object; otherwise the
- corresponding Python argument will be None.
-
-
if you want by-reference behavior, use ptr(aN) if
- aN is a pointer and ref(aN) otherwise. If a
- null pointer is passed to ptr(aN), the corresponding
- Python argument will be None.
-
-
-
As for results, we have a similar problem: if ResultType
- is allowed to be a pointer or reference type, the lifetime of the object
- it refers to is probably being managed by a Python object. When that
- Python object is destroyed, our pointer dangles. The problem is
- particularly bad when the ResultType is char const* - the
- corresponding Python String object is typically uniquely-referenced,
- meaning that the pointer dangles as soon as call<char
- const*>(...) returns.
-
-
The old Boost.Python v1 deals with this issue by refusing to compile
- any uses of call<char const*>(), but this goes both
- too far and not far enough. It goes too far because there are cases where
- the owning Python string object survives beyond the call (just for
- instance, when it's the name of a Python class), and it goes not far
- enough because we might just as well have the same problem with a
- returned pointer or reference of any other type.
-
-
In Boost.Python v2 this is dealt with by:
-
-
-
lifting the compile-time restriction on const char* callback
- returns
-
-
detecting the case when the reference count on the result Python
- object is 1 and throwing an exception inside of
- call<U>(...) when U is a pointer or
- reference type.
-
- This should be acceptably safe because users have to explicitly specify a
- pointer/reference for U in call<U>, and
- they will be protected against dangles at runtime, at least long enough
- to get out of the call<U>(...) invocation.
-
- [1] It would be possible to make it fail at compile-time
- for non-class types such as int and char, but I'm not sure it's a good
- idea to impose this restriction yet.
-
-
-
-
-
diff --git a/doc/v2/callbacks.txt b/doc/v2/callbacks.txt
deleted file mode 100644
index 2795680f..00000000
--- a/doc/v2/callbacks.txt
+++ /dev/null
@@ -1,92 +0,0 @@
-.. Copyright David Abrahams 2006. Distributed under the Boost
-.. Software License, Version 1.0. (See accompanying
-.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-Here's the plan:
-
-I aim to provide an interface similar to that of Boost.Python v1's
-callback<>::call(...) for dealing with callbacks. The interface will
-look like:
-
- returning::call("method_name", self_object, a1, a2...);
-
-or
-
- returning::call(callable_object, a1, a2...);
-
-ARGUMENT HANDLING
-
-There is an issue concerning how to make Python objects from the
-arguments a1...aN. A new Python object must be created; should the C++
-object be copied into that Python object, or should the Python object
-simply hold a reference/pointer to the C++ object? In general, the
-latter approach is unsafe, since the called function may store a
-reference to the Python object somewhere. If the Python object is used
-after the C++ object is destroyed, we'll crash Python.
-
-I plan to make the copying behavior the default, and to allow a
-non-copying behavior if the user writes boost::ref(a1) instead of a1
-directly. At least this way, the user doesn't get dangerous behavior "by
-accident". It's also worth noting that the non-copying ("by-reference")
-behavior is in general only available for class types, and will fail at
-runtime with a Python exception if used otherwise**
-
-However, pointer types present a problem: My first thought is to refuse
-to compile if any aN has pointer type: after all, a user can always pass
-*aN to pass "by-value" or ref(*aN) to indicate a pass-by-reference
-behavior. However, this creates a problem for the expected NULL pointer
-=> None conversion: it's illegal to dereference a null pointer value.
-
-We could use another construct, say "ptr(aN)", to deal with null
-pointers, but then what does it mean? We know what it does when aN is
-NULL, but it might either have by-value or by-reference behavior when aN
-is non-null.
-
-The compromise I've settled on is this:
-
-1. The default behavior is pass-by-value. If you pass a non-null
- pointer, the pointee is copied into a new Python object; otherwise
- the corresponding Python argument will be None.
-
-2. if you want by-reference behavior, use ptr(aN) if aN is a pointer
- and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the
- corresponding Python argument will be None.
-
-RESULT HANDLING
-
-As for results, we have a similar problem: if ResultType is allowed to
-be a pointer or reference type, the lifetime of the object it refers to
-is probably being managed by a Python object. When that Python object is
-destroyed, our pointer dangles. The problem is particularly bad when the
-ResultType is char const* - the corresponding Python String object is
-typically uniquely-referenced, meaning that the pointer dangles as soon
-as returning::call() returns.
-
-Boost.Python v1 deals with this issue by refusing to compile any uses of
-callback::call(), but IMO this goes both too far and not
-far enough. It goes too far because there are cases where the owning
-String object survives beyond the call (just for instance when it's the
-name of a Python class), and it goes not far enough because we might
-just as well have the same problem with any returned pointer or
-reference.
-
-I propose to address this in Boost.Python v2 by
-
- 1. lifting the compile-time restriction on const
- char* callback returns
-
- 2. detecting the case when the reference count on the
- result Python object is 1 and throwing an exception
- inside of returning::call() when U is a pointer or
- reference type.
-
-I think this is acceptably safe because users have to explicitly specify
-a pointer/reference for U in returning, and they will be protected
-against dangles at runtime, at least long enough to get out of the
-returning::call() invocation.
-
--Dave
-
-**It would be possible to make it fail at compile-time for non-class
-types such as int and char, but I'm not sure it's a good idea to impose
-this restriction yet.
diff --git a/doc/v2/class.html b/doc/v2/class.html
deleted file mode 100644
index edfc6097..00000000
--- a/doc/v2/class.html
+++ /dev/null
@@ -1,790 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Boost.Python - <boost/python/class.hpp>,
- <boost/python/class_fwd.hpp>
-
-
-
-
<boost/python/class.hpp> defines the interface
- through which users expose their C++ classes to Python. It declares the
- class_ class template, which is parameterized on the class
- type being exposed. It also exposes the init,
- optional and bases utility class templates, which
- are used in conjunction with class_.
-
-
<boost/python/class_fwd.hpp> contains a forward
- declaration of the class_ class template.
-
-
Classes
-
-
Class template
- class_<T, Bases, HeldType,
- NonCopyable>
-
-
Creates a Python class associated with the C++ type passed as its first
- parameter. Although it has four template parameters, only the first one is
- required. The three optional arguments can actually be supplied
- in any order; Boost.Python determines
- the role of the argument from its type.
-
-
-
-
-
Template Parameter
-
-
Requirements
-
-
Semantics
-
-
Default
-
-
-
-
T
-
-
A class type.
-
-
The class being wrapped
-
-
-
-
Bases
-
-
A specialization of bases<...> which
- specifies previously-exposed C++ base classes of T[1].
-
-
Registers from_python conversions from wrapped
- T instances to each of its exposed direct and indirect
- bases. For each polymorphic base B, registers conversions
- from indirectly-held wrapped B instances to
- T.
Must be T, a class derived from T, or a
- Dereferenceable type for which
- pointee<HeldType>::type is
- T or a class derived from T.
-
-
Specifies the type that is actually embedded in a Python object
- wrapping a T instance when T's constructor is
- called or when a T or T* is converted to
- Python without the use of
- ptr,
- ref, or Call Policies
- such as return_internal_reference.
- More details below.
If HeldType is derived from T, its exposed
- constructor(s) must accept an initial PyObject* argument
- which refers back to the Python object that contains the
- HeldType instance, as shown in this example. This argument is not
- included in the init-expression passed to def(init_expr), below, nor is
- it passed explicitly by users when Python instances of T are
- created. This idiom allows C++ virtual functions which will be overridden
- in Python to access the Python object so the Python method can be
- invoked. Boost.Python automatically registers additional converters which
- allow wrapped instances of T to be passed to wrapped C++
- functions expecting HeldType arguments.
-
-
Because Boost.Python will always allow wrapped instances of
- T to be passed in place of HeldType arguments,
- specifying a smart pointer for HeldType allows users to pass
- Python T instances where a smart pointer-to-T
- is expected. Smart pointers such as std::auto_ptr<> or
- boost::shared_ptr<>
- which contain a nested type element_type designating the
- referent type are automatically supported; additional smart pointer types
- can be supported by specializing pointee<HeldType>.
-
-
As in case 1 above, when HeldType is a smart pointer to
- a class derived from T, the initial PyObject*
- argument must be supplied by all of HeldType's exposed
- constructors.
-
-
Except in cases 1 and 3, users may optionally specify that T itself
- gets initialized with a similar initial PyObject* argument
- by specializing has_back_reference<T>.
Requires:name is an ntbs which conforms to Python's identifier
- naming rules. If docstring is supplied, it must be an
- ntbs. If init_spec is
- supplied, it must be either the special enumeration constant
- no_init or an init-expression compatible with
- T.
-
-
Effects: Constructs a class_ object holding a
- Boost.Python extension class named name. The
- named attribute of the current scope is bound to the new extension
- class.
-
-
-
-
If supplied, the value of docstring is bound to the
- __doc__ attribute of the extension class.
-
-
If init_spec is no_init, a special
- __init__ function is generated which always raises a
- Python exception. Otherwise, this->def(init_spec) is
- called.
-
-
If init_spec is not supplied,
- this->def(init<>()) is called.
-
-
-
-
Rationale:Allowing the user to specify constructor arguments
- in the class_<> constructor helps her to avoid the
- common run-time errors which result from invoking wrapped member
- functions without having exposed an __init__ function which
- creates the requisite T instance. Types which are not
- default-constructible will cause a compile-time error unless
- Init is supplied. The user must always supply
- name as there is currently no portable method to derive the
- text of the class name from its type.
Requires:init_expr is the result of an init-expression compatible with
- T.
-
-
Effects: For each valid
- prefixP of Init, adds an
- __init__(...) function overload to the
- extension class accepting P as arguments. Each overload
- generated constructs an object of HeldType according to the
- semantics described above, using a copy of
- init_expr's call policies.
- If the longest valid prefix of
- Init contains N types and init_expr
- holds M keywords, an initial sequence of the keywords are used
- for all but the first N - M arguments of each
- overload.
-
-
Returns:*this
-
-
Rationale: Allows users to easily expose a class' constructor
- to Python.
If a1 is the result of an overload-dispatch-expression,
- only the second form is allowed and fn must be a pointer to function
- or pointer to member function whose
- arity is the same as A1's maximum
- arity.
-
-
-
Effects: For each prefix P of
- Fn's sequence of argument types, beginning with the
- one whose length is A1's minimum
- arity, adds a
- name(...) method overload to
- the extension class. Each overload generated invokes
- a1's call-expression with P, using a copy
- of a1's call
- policies. If the longest valid prefix of A1
- contains N types and a1 holds M
- keywords, an initial sequence of the keywords are used for all
- but the first N - M arguments of each
- overload.
-
-
-
-
Otherwise, a single method overload is built around fn, which
- must not be null:
-
-
-
If fn is a function pointer, its first argument must be of
- the form U, U cv&, U
- cv*, or U cv* const&,
- where T* is convertible to U*, and
- a1-a3, if supplied, may be selected in
- any order from the table below.
-
-
Otherwise, if fn is a member function pointer, its target
- must be T or one of its public base classes, and
- a1-a3, if supplied, may be selected in
- any order from the table below.
-
-
Otherwise, Fn must be [derived from]
- object, and
- a1-a2, if supplied, may be selcted in any order from
- the first two rows of the table below. To be useful,
- fn should be
- callable.
Value will be bound to the __doc__ attribute
- of the resulting method overload. If an earlier overload
- supplied a docstring, two newline characters and the new
- docstring are appended to it.
A copy will be used as the call policies of the resulting
- method overload.
-
-
-
-
-
-
-
Returns:*this
-
-
-class_& staticmethod(char const* name);
-
-
-
-
Requires:name is an ntbs which conforms to Python's identifier
- naming rules, and corresponds to a method whose overloads have all
- been defined.
-
-
Effects: Replaces the existing named attribute x with
- the result of invoking staticmethod(x)
- in Python. Specifies that the corresponding method is static and
- therefore no object instance will be passed to it. This is equivalent to
- the Python statement:
Effects: Creates a new Python property
- class instance, passing object(fget) (and
- object(fset) in
- the second form) with an (optional) docstring doc to its
- constructor, then adds that property to the Python class object under
- construction with the given attribute name.
-
-
Returns:*this
-
-
Rationale: Allows users to easily expose functions that can be
- invoked from Python with attribute access syntax.
-
-
-template <class Get>
-void add_static_property(char const* name, Get const& fget);
-template <class Get, class Set>
-void add_static_property(char const* name, Get const& fget, Set const& fset);
-
Effects: Creates a Boost.Python.StaticProperty object, passing
- object(fget)
- (and object(fset) in the second
- form) to its constructor, then adds that property to the Python class
- under construction with the given attribute name.
- StaticProperty is a special subclass of Python's property
- class which can be called without an initial self
- argument.
-
-
Returns:*this
-
-
Rationale: Allows users to easily expose functions that can be
- invoked from Python with static attribute access syntax.
Rationale: Allows users to easily expose a class' data or free
- variable member such that it can be inspected and set from Python with a
- natural syntax.
Requires: PickleSuite must be publically derived from pickle_suite.
-
-
Effects: Defines a legal combination of the special attributes
- and methods: __getinitargs__, __getstate__,
- __setstate__, __getstate_manages_dict__,
- __safe_for_unpickling__, __reduce__
-
-
Returns:*this
-
-
Rationale: Provides an easy to use
- high-level interface for establishing complete pickle support for the
- wrapped class. The user is protected by compile-time consistency
- checks.
-
-
-class_& enable_pickling();
-
-
-
-
Effects: Defines the __reduce__ method and the
- __safe_for_unpickling__ attribute.
-
-
Returns:*this
-
-
Rationale: Light-weight alternative to
- def_pickle(). Enables implementation of pickle support from Python.
-
-
-
Class template
- bases<T1, T2,...TN>
-
-
An MPL
- sequence which can be used in
- class_<...> instantiations indicate a list
- of base classes.
Boost.Python uses several configuration macros in <boost/config.hpp>,
- as well as configuration macros meant to be supplied by the application.
- These macros are documented here.
-
-
Application Defined Macros
-
-
These are the macros that may be defined by an application using
- Boost.Python. Note that if you extend a strict interpretation of
- the C++ standard to cover dynamic libraries, using different values of
- these macros when compiling different libraries (including extension
- modules and the Boost.Python library itself) is a violation of the
- ODR. However, we know of no C++
- implementations on which this particular violation is detectable or
- causes any problems.
-
-
-
-
Macro
-
-
Default
-
-
Meaning
-
-
-
-
BOOST_PYTHON_MAX_ARITY
-
-
15
-
-
The maximum arity of any function, member function,
- or constructor to be wrapped, invocation of a Boost.Python
- function wich is specified as taking arguments
- x1, x2,...Xn. This includes, in
- particular, callback mechanisms such as object::operator()(...)
- or call_method<R>(...
- ).
-
-
-
-
BOOST_PYTHON_MAX_BASES
-
-
10
-
-
The maximum number of template arguments to the
- bases<...>
- class template, which is used to specify the bases of a wrapped C++
- class..
-
-
-
-
BOOST_PYTHON_STATIC_MODULE
-
-
not defined
-
-
If defined, prevents your module initialization
- function from being treated as an exported symbol on platforms which
- support that distinction in-code
-
-
-
-
BOOST_PYTHON_ENABLE_CDECL
-
-
not defined
-
-
If defined, allows functions using the __cdecl
- calling convention to be wrapped.
-
-
-
-
BOOST_PYTHON_ENABLE_STDCALL
-
-
not defined
-
-
If defined, allows functions using the __stdcall
- calling convention to be wrapped.
-
-
-
-
BOOST_PYTHON_ENABLE_FASTCALL
-
-
not defined
-
-
If defined, allows functions using the __fastcall
- calling convention to be wrapped.
-
-
-
-
Library Defined Implementation
- Macros
-
-
These macros are defined by Boost.Python and are implementation
- details of interest only to implementors and those porting to new
- platforms.
-
-
-
-
Macro
-
-
Default
-
-
Meaning
-
-
-
-
BOOST_PYTHON_TYPE_ID_NAME
-
-
not defined
-
-
If defined, this indicates that the type_info
- comparison across shared library boundaries does not work on this
- platform. In other words, if shared-lib-1 passes
- typeid(T) to a function in shared-lib-2 which compares
- it to typeid(T), that comparison may return
- false. If this macro is #defined, Boost.Python uses and
- compares typeid(T).name() instead of using and comparing
- the std::type_info objects directly.
-
-
-
BOOST_PYTHON_NO_PY_SIGNATURES
-
-
not defined
-
-
If defined for a module no pythonic signatures are generated
- for the docstrings of the module functions, and no python type is associated with any
- of the converters registered by the module. This also reduces the binary size of the
- module by about 14% (gcc compiled).
- If defined for the boost_python runtime library, the default for the
- docstring_options.enable_py_signatures() is set to false.
-
-
-
-
-
BOOST_PYTHON_SUPPORTS_PY_SIGNATURES
-
-
defined if BOOST_PYTHON_NO_PY_SIGNATURES is undefined
-
-
This macro is defined to enable a smooth transition from older Boost.Python versions
- which do not support pythonic signatures. For example usage see
- here.
-
-
-
-
-
BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE
-
-
not defined
-
-
If defined the python type of __init__ method "self" parameters
- is properly generated, otherwise object is used. It is undefined
- by default because it increases the binary size of the module by about 14% (gcc compiled).
copy_const_reference is a model of ResultConverterGenerator
- which can be used to wrap C++ functions returning a reference-to-const
- type such that the referenced value is copied into a new Python
- object.
copy_non_const_reference is a model of ResultConverterGenerator
- which can be used to wrap C++ functions returning a
- reference-to-non-const type such that the referenced value is copied into
- a new Python object.
make_getter() and
- make_setter() are the
- functions used internally by class_<>::def_readonly and
- class_<>::def_readwrite to produce
- Python callable objects which wrap C++ data members.
-
-
Functions
-
-template <class C, class D>
-object make_getter(D C::*pm);
-
-template <class C, class D, class Policies>
-object make_getter(D C::*pm, Policies const& policies);
-
Effects: Creates a Python callable object which accepts a
- single argument that can be converted from_python to
- C*, and returns the corresponding member D
- member of the C object, converted to_python.
- If policies is supplied, it will be applied to the
- function as described here. Otherwise,
- the library attempts to determine whether D is a
- user-defined class type, and if so uses return_internal_reference<>
-
-
for Policies. Note that this test may inappropriately
- choose return_internal_reference<> in some cases
- when D is a smart pointer type. This is a known
- defect.
-
-
Returns: An instance of object which holds the new Python
- callable object.
Effects: Creates a Python callable object which accepts no
- arguments and returns d or *p, converted
- to_python on demand. If policies is supplied,
- it will be applied to the function as described here. Otherwise, the library attempts to
- determine whether D is a user-defined class type, and if
- so uses reference_existing_object
-
-
for Policies.
-
-
Returns: An instance of object which holds the new Python
- callable object.
-
-
-template <class C, class D>
-object make_setter(D C::*pm);
-
-template <class C, class D, class Policies>
-object make_setter(D C::*pm, Policies const& policies);
-
Effects: Creates a Python callable object which, when called
- from Python, expects two arguments which can be converted
- from_python to C* and
- D const&, respectively, and sets the
- corresponding D member of the C object. If
- policies is supplied, it will be applied to the function
- as described here.
-
-
Returns: An instance of object which holds the new Python
- callable object.
Effects: Creates a Python callable object which accepts one
- argument, which is converted from Python to D const&
- and written into d or *p, respectively. If
- policies is supplied, it will be applied to the function
- as described here.
-
-
Returns: An instance of object which holds the new Python
- callable object.
-
-
-
Example
-
-
The code below uses make_getter and make_setter to expose a data
- member as functions:
If Fn is [derived from] object, it will be added to
- the current scope as a single overload. To be useful,
- fn should be callable.
-
-
- If a1 is the result of an overload-dispatch-expression,
- only the second form is allowed and fn must be a pointer to
- function or pointer to member function whose arity is the same as A1's maximum
- arity.
-
-
-
Effects: For each prefix P of
- Fn's sequence of argument types, beginning with
- the one whose length is A1's minimum
- arity, adds a
- name(...) function overload
- to the current scope. Each overload
- generated invokes a1's call-expression with
- P, using a copy of a1's call policies. If the longest valid
- prefix of A1 contains N types and
- a1 holds M keywords, an initial sequence
- of the keywords are used for all but the first
- N - M arguments of each
- overload.
-
-
-
-
-
Otherwise, fn must be a non-null function or member function
- pointer, and a single function overload built around fn is added to
- the current scope. If any of
- a1-a3 are supplied, they may be selected
- in any order from the table below.
<boost/python/def_visitor.hpp> provides a generic visitation
- interface through which the class_def member
- functionality can be extended non-intrusively to avoid cluttering the class_
- interface. It declares the def_visitor<T> class template,
- which is parameterized on the derived type DerivedVisitor, which provides
- the actual def functionality through its visit member functions.
-
Classes
-
-
Class template def_visitor<DerivedVisitor>
-
-
-
The class def_visitor is a base class paramaterized by its derived class. The
- def_visitor class is a protocol class. Its derived class, DerivedVisitor, is
- expected to have a member function visit. The def_visitor class is never instantiated
- directly. Instead, an instance of its subclass, DerivedVisitor, is passed
- on as an argument to the class_ def member function.
-
default_call_policies is a model of CallPolicies with no precall or
- postcall behavior and a result_converter which
- handles by-value returns. Wrapped C++ functions and member functions use
- default_call_policies unless otherwise specified. You may find
- it convenient to derive new models of CallPolicies from
- default_call_policies.
-
-
default_result_converter is a model of ResultConverterGenerator which can be
- used to wrap C++ functions returning non-pointer types, char
- const*, and PyObject*, by-value.
-
-
This example comes from the Boost.Python implementation itself. Because
- the return_value_policy
- class template does not implement precall or
- postcall behavior, its default base class is
- default_call_policies:
-
-template <class Handler, class Base = default_call_policies>
-struct return_value_policy : Base
-{
- typedef Handler result_converter;
-};
-
arity: The number of arguments accepted
- by a function or member function. Unless otherwise specified, the
- hidden "this" argument to member functions is not counted
- when specifying arity
-
-
-
-
-
ntbs: Null-Terminated Byte String, or
- `C'-string. C++ string literals are ntbses. An
- ntbs must never be null.
-
-
-
-
-
raise: Exceptions in Python are
- "raised", not "thrown", as they are in C++. When this documentation
- says that some Python exception is "raised" in the context of C++ code,
- it means that the corresponding Python exception is set via the Python/'C'
- API, and throw_error_already_set()
- is called.
-
-
-
-
-
POD: A technical term from the C++
- standard. Short for "Plain Ol'Data": A POD-struct is an aggregate class
- that has no non-static data members of type pointer to member,
- non-POD-struct, non-POD-union (or array of such types) or reference,
- and has no user-defined copy assign- ment operator and no user-defined
- destructor. Similarly, a POD-union is an aggregate union that has no
- non-static data members of type pointer to member, non-POD-struct,
- non-POD-union (or array of such types) or reference, and has no
- user-defined copy assignment operator and no user-defined destructor. A
- POD class is a class that is either a POD-struct or a POD-union. An
- aggregate is an array or a class (clause 9) with no user-declared
- constructors (12.1), no private or protected non-static data members
- (clause 11), no base classes (clause 10), and no virtual functions
- (10.3).
-
-
-
-
-
ODR: The "One Definition
- Rule", which says that any entity in a C++ program must have the same definition in all translation units (object files) which make up a program.
-
Exposes the mapping
- protocol of Python's built-in dict type. The semantics
- of the constructors and member functions defined below can be fully
- understood by reading the TypeWrapper concept
- definition. Since dict is publicly derived from object, the public object
- interface applies to dict instances as well.
Boost.Python supports user-defined docstrings with automatic
- appending of C++ signatures. These features are enabled by
- default. The class docstring_options is available to
- selectively suppress the user-defined docstrings, signatures, or
- both.
-
-
Classes
-
-
Class
- docstring_options
-
-
Controls the appearance of docstrings of wrapped functions and
- member functions for the life-time of the instance. The instances
- are noncopyable to eliminate the possibility of surprising side
- effects.
Effects: Constructs a docstring_options
- object which controls the appearance of function and
- member-function docstrings defined in the code that follows. If
- show_all is true, both the
- user-defined docstrings and the automatically generated Python and C++
- signatures are shown. If show_all is
- false the __doc__ attributes are
- None.
Effects: Constructs a docstring_options
- object which controls the appearance of function and
- member-function docstrings defined in the code that follows.
- Iff show_user_defined is true, the
- user-defined docstrings are shown. Iff
- show_signatures is true, Python and C++
- signatures are automatically added. If both
- show_user_defined and show_signatures
- are false, the __doc__ attributes are
- None.
Effects: Constructs a docstring_options
- object which controls the appearance of function and
- member-function docstrings defined in the code that follows.
- Iff show_user_defined is true, the
- user-defined docstrings are shown. Iff
- show_py_signatures is true, Python
- signatures are automatically added. Iff
- show_cpp_signatures is true, C++
- signatures are automatically added. If all parameters are
- false, the __doc__ attributes are
- None.
-
-
-
Class
- docstring_options destructors
-
-~docstring_options();
-
-
-
-
Effects: Restores the previous state of the
- docstring options. In particular, if
- docstring_options instances are in nested C++
- scopes the settings effective in the enclosing scope are
- restored. If the last docstring_options instance
- goes out of scope the default "all on" settings are
- restored.
These member functions dynamically change the appearance of
- docstrings in the code that follows. The
- *_user_defined() and *_signatures()
- member functions are provided for fine-grained control. The
- *_all() member functions are convenient shortcuts
- to manipulate all settings simultaneously.
<boost/python/enum.hpp> defines the
- interface through which users expose their C++ enumeration types
- to Python. It declares the
- enum_ class template, which is parameterized on the
- enumeration type being exposed.
-
-
-
Classes
-
-
Class template
- enum_<T>
-
-
Creates a Python class derived from Python's int
- type which is associated with the C++ type passed as its first
- parameter.
-
-
Effects: Constructs an enum_ object
- holding a Python extension type derived from int
- which is named name. The
- named attribute of the current scope is bound to the new
- extension type.
<boost/python/errors.hpp> provides types and
- functions for managing and translating between Python and C++ exceptions.
- This is relatively low-level functionality that is mostly used internally
- by Boost.Python. Users should seldom need it.
-
-
Classes
-
-
Class
- error_already_set
-
-
error_already_set is an exception type which can be
- thrown to indicate that a Python error has occurred. If thrown, the
- precondition is that PyErr_Occurred()
- returns a value convertible to true. Portable code shouldn't
- throw this exception type directly, but should instead use throw_error_already_set(),
- below.
Requires: The first form requires that the expression
- function0<void>(f)
- is valid. The second form requires that a C++ exception is currently
- being handled (see section 15.1 in the C++ standard).
-
-
Effects: The first form calls f() inside a
- try block which first attempts to use all registered exception translators. If none of
- those translates the exception, the catch clauses then set
- an appropriate Python exception for the C++ exception caught, returning
- true if an exception was thrown, false
- otherwise. The second form passes a function which rethrows the
- exception currently being handled to the first form.
-
-
Postconditions: No exception is being handled
-
-
Throws: nothing
-
-
Rationale: At inter-language boundaries it is important to
- ensure that no C++ exceptions escape, since the calling language
- usually doesn't have the equipment necessary to properly unwind the
- stack. Use handle_exception to manage exception
- translation whenever your C++ code is called directly from the Python
- API. This is done for you automatically by the usual function wrapping
- facilities: make_function(),
- make_constructor(),
- def() and class_::def(). The second form can be
- more convenient to use (see the example below),
- but various compilers have problems when exceptions are rethrown from
- within an enclosing try block.
Rationale: Many platforms and compilers are not able to
- consistently catch exceptions thrown across shared library boundaries.
- Using this function from the Boost.Python library ensures that the
- appropriate catch block in handle_exception() can catch the
- exception.
-
-
-
Examples
-
-#include <string>
-#include <boost/python/errors.hpp>
-#include <boost/python/object.hpp>
-#include <boost/python/handle.hpp>
-
-// Returns a std::string which has the same value as obj's "__name__"
-// attribute.
-std::string get_name(boost::python::object obj)
-{
- // throws if there's no __name__ attribute
- PyObject* p = boost::python::expect_non_null(
- PyObject_GetAttrString(obj.ptr(), "__name__"));
-
- char const* s = PyString_AsString(p);
- if (s != 0)
- Py_DECREF(p);
-
- // throws if it's not a Python string
- std::string result(
- boost::python::expect_non_null(
- PyString_AsString(p)));
-
- Py_DECREF(p); // Done with p
-
- return result;
-}
-
-//
-// Demonstrate form 1 of handle_exception
-//
-
-// Place into result a Python Int object whose value is 1 if a and b have
-// identical "__name__" attributes, 0 otherwise.
-void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
-{
- result = PyInt_FromLong(
- get_name(a) == get_name(a2));
-}
-
-object borrowed_object(PyObject* p)
-{
- return boost::python::object(
- boost::python::handle<>(
- boost::python::borrowed(a1)));
-}
-
-// This is an example Python 'C' API interface function
-extern "C" PyObject*
-same_name(PyObject* args, PyObject* keywords)
-{
- PyObject* a1;
- PyObject* a2;
- PyObject* result = 0;
-
- if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
- return 0;
-
- // Use boost::bind to make an object compatible with
- // boost::Function0<void>
- if (boost::python::handle_exception(
- boost::bind<void>(same_name_impl, boost::ref(result), borrowed_object(a1), borrowed_object(a2))))
- {
- // an exception was thrown; the Python error was set by
- // handle_exception()
- return 0;
- }
-
- return result;
-}
-
-//
-// Demonstrate form 2 of handle_exception. Not well-supported by all
-// compilers.
-//
-extern "C" PyObject*
-same_name2(PyObject* args, PyObject* keywords)
-{
- PyObject* a1;
- PyObject* a2;
- PyObject* result = 0;
-
- if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
- return 0;
-
- try {
- return PyInt_FromLong(
- get_name(borrowed_object(a1)) == get_name(borrowed_object(a2)));
- }
- catch(...)
- {
- // If an exception was thrown, translate it to Python
- boost::python::handle_exception();
- return 0;
- }
-}
-
As described here, it
- is important to make sure that exceptions thrown by C++ code do not pass
- into the Python interpreter core. By default, Boost.Python translates all
- C++ exceptions thrown by wrapped functions and module init functions into
- Python, but the default translators are extremely limited: most C++
- exceptions will appear in Python as a RuntimeError
- exception whose representation is
- 'Unidentifiable C++ Exception'. To produce better
- error messages, users can register additional exception translators as
- described below.
- Translate is Copyconstructible, and
- the following code must be well-formed:
-
-void f(ExceptionType x) { translate(x); }
-
- The expression translate(x) must either throw a C++
- exception, or a subsequent call to PyErr_Occurred()
- must return 1.
-
-
-
-
-
Effects: Adds a copy of translate to the sequence of
- exception translators tried when Boost.Python catches an exception that
- is about to pass into Python's core interpreter. The new translator
- will get "first shot" at translating all exceptions matching the catch
- clause shown above. Any subsequently-registered translators will be
- allowed to translate the exception earlier. A translator which cannot
- translate a given C++ exception can re-throw it, and it will be handled
- by a translator which was registered earlier (or by the default
- translator).
-
-
-
Example
-
-#include <boost/python/module.hpp>
-#include <boost/python/def.hpp>
-#include <boost/python/exception_translator.hpp>
-#include <exception>
-
-struct my_exception : std::exception
-{
- char const* what() throw() { return "One of my exceptions"; }
-};
-
-void translate(my_exception const& e)
-{
- // Use the Python 'C' API to set up an exception object
- PyErr_SetString(PyExc_RuntimeError, e.what());
-}
-
-void something_which_throws()
-{
- ...
- throw my_exception();
- ...
-}
-
-BOOST_PYTHON_MODULE(exception_translator_ext)
-{
- using namespace boost::python;
- register_exception_translator<my_exception>(&translate);
-
- def("something_which_throws", something_which_throws);
-}
-
Exposes a mechanism for extracting C++ object values from
- generalized Python objects. Note that
- extract<...> can also be used to
- "downcast" an object to some specific ObjectWrapper. Because
- invoking a mutable python type with an argument of the same type
- (e.g. list([1,2]) typically makes a copy of
- the argument object, this may be the only way to access the ObjectWrapper's
- interface on the original object.
-
-
Classes
-
-
Class template extract
-
-
extract<T> can be used to extract a value of
- an arbitrary C++ type from an instance of object. Two usages are supported:
-
-
extract<T>(o) is a temporary object
-which is implicitly convertible to T (explicit conversion
-is also available through the object's function-call
-operator). However, if no conversion is available which can convert
-o to an object of type T, a Python
-TypeError exception will be raised.
-
-
extract<T> x(o); constructs an extractor
-whose check() member function can be used to ask whether
-a conversion is available without causing an exception to be thrown.
-
Requires: The first form requires that p is non-null.
-
-
Effects:Stores a pointer to the Python object managed
- by its constructor argument. In particular, the reference
- count of the object is not incremented. The onus is on the user
- to be sure it is not destroyed before the extractor's conversion
- function is called.
Effects: Converts the stored pointer to
- result_type, which is either T or
- T const&.
-
-
-
Returns: An object of result_type
- corresponding to the one referenced by the stored pointer.
-
-
Throws:error_already_set
- and sets a TypeError if no such conversion is
- available. May also emit other unspecified exceptions thrown by
- the converter which is actually used.
-
-
-
-bool check() const;
-
-
-
-
-
Postconditions: None. In particular, note that a
- return value of true does not preclude an exception
- being thrown from operator result_type() or
- operator()().
-
-
Returns:falseonly if no conversion from the
- stored pointer to T is available.
-
-
-
-
-
Examples
-
-
-#include <cstdio>
-using namespace boost::python;
-int Print(str s)
-{
- // extract a C string from the Python string object
- char const* c_str = extract<char const*>(s);
-
- // Print it using printf
- std::printf("%s\n", c_str);
-
- // Get the Python string's length and convert it to an int
- return extract<int>(s.attr("__len__")())
-}
-
-
-The following example shows how extract can be used along with
-class_<...>
-to create and access an instance of a wrapped C++ class.
-
-
-struct X
-{
- X(int x) : v(x) {}
- int value() { return v; }
- private:
- int v;
-};
-
-BOOST_PYTHON_MODULE(extract_ext)
-{
- object x_class(
- class_<X>("X", init<int>())
- .def("value", &X::value))
- ;
-
- // Instantiate an X object through the Python interface.
- // Its lifetime is now managed by x_obj.
- object x_obj = x_class(3);
-
- // Get a reference to the C++ object out of the Python object
- X& x = extract<X&>(x_obj);
- assert(x.value() == 3);
-}
-
-
- The short answer is: "you can't". This is not a
- Boost.Python limitation so much as a limitation of C++. The
- problem is that a Python function is actually data, and the only
- way of associating data with a C++ function pointer is to store it
- in a static variable of the function. The problem with that is
- that you can only associate one piece of data with every C++
- function, and we have no way of compiling a new C++ function
- on-the-fly for every Python function you decide to pass
- to foo. In other words, this could work if the C++
- function is always going to invoke the same Python
- function, but you probably don't want that.
-
-
If you have the luxury of changing the C++ code you're
- wrapping, pass it an object instead and call that;
- the overloaded function call operator will invoke the Python
- function you pass it behind the object.
-
-
For more perspective on the issue, see this
- posting.
-
-
-ReferenceError: Attempt to return dangling reference to object of type:
-class period
-
-
-
In this case, the Python method invoked by call_method
- constructs a new Python object. You're trying to return a reference to a
- C++ object (an instance of class period) contained within
- and owned by that Python object. Because the called method handed back a
- brand new object, the only reference to it is held for the duration of
- get_floating_frequency() above. When the function returns,
- the Python object will be destroyed, destroying the instance of
- class period, and leaving the returned reference dangling.
- That's already undefined behavior, and if you try to do anything with
- that reference you're likely to cause a crash. Boost.Python detects this
- situation at runtime and helpfully throws an exception instead of letting
- you do that.
-
-
-
-
Is return_internal_reference efficient?
-
-
- Q:I have an object composed of 12 doubles. A const& to
- this object is returned by a member function of another class. From the
- viewpoint of using the returned object in Python I do not care if I get
- a copy or a reference to the returned object. In Boost.Python Version 2
- I have the choice of using copy_const_reference or
- return_internal_reference. Are there considerations that would lead me
- to prefer one over the other, such as size of generated code or memory
- overhead?
-
-
A: copy_const_reference will make an instance with storage
- for one of your objects, size = base_size + 12 * sizeof(double).
- return_internal_reference will make an instance with storage for a
- pointer to one of your objects, size = base_size + sizeof(void*).
- However, it will also create a weak reference object which goes in the
- source object's weakreflist and a special callback object to manage the
- lifetime of the internally-referenced object. My guess?
- copy_const_reference is your friend here, resulting in less overall
- memory use and less fragmentation, also probably fewer total
- cycles.
-
-
-
-
How can I wrap functions which take C++
- containers as arguments?
- This can be moved to a template so that several types (double, int,
- long, etc.) can be wrapped with the same code. This technique is used
- in the file
-
-
- This code can be used to convert from C++ container types such as
- std::vector<> or std::list<> to Python tuples and vice
- versa. A few simple examples can be found in the file
-
-
- Automatic C++ container <-> Python tuple conversions are most
- suitable for containers of moderate size. These converters generate
- significantly less object code compared to alternative 1 above.
-
-
- A disadvantage of using alternative 2 is that operators such as
- arithmetic +,-,*,/,% are not available. It would be useful to have custom
- rvalue converters that convert to a "math_array" type instead of tuples.
- This is currently not implemented but is possible within the framework of
- Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
- this was posted on 2002/03/10]
-
-
It would also be useful to also have "custom lvalue converters" such
- as std::vector<> <-> Python list. These converters would
- support the modification of the Python list from C++. For example:
- If you find that a class_<...> declaration
- can't fit in a single source file without triggering the error, you
- can always pass a reference to the class_ object to a
- function in another source file, and call some of its member
- functions (e.g. .def(...)) in the auxilliary source
- file:
-
-
Greg Burley gives the following answer for Unix GCC users:
-
-
- Once you have created a boost python extension for your c++ library or
- class, you may need to debug the code. Afterall this is one of the
- reasons for wrapping the library in python. An expected side-effect or
- benefit of using BPL is that debugging should be isolated to the c++
- library that is under test, given that python code is minimal and
- boost::python either works or it doesn't. (ie. While errors can occur
- when the wrapping method is invalid, most errors are caught by the
- compiler ;-).
-
-
The basic steps required to initiate a gdb session to debug a c++
- library via python are shown here. Note, however that you should start
- the gdb session in the directory that contains your BPL my_ext.so
- module.
-
-(gdb) target exec python
-(gdb) run
- >>> from my_ext import *
- >>> [C-c]
-(gdb) break MyClass::MyBuggyFunction
-(gdb) cont
- >>> pyobj = MyClass()
- >>> pyobj.MyBuggyFunction()
-Breakpoint 1, MyClass::MyBuggyFunction ...
-Current language: auto; currently c++
-(gdb) do debugging stuff
-
-
-
-
Greg's approach works even better using Emacs' "gdb"
- command, since it will show you each line of source as you step through
- it.
-
-
On Windows, my favorite debugging solution is the debugger that
- comes with Microsoft Visual C++ 7. This debugger seems to work with code
- generated by all versions of Microsoft and Metrowerks toolsets; it's rock
- solid and "just works" without requiring any special tricks from the
- user.
-
-
Raoul Gough has provided the following for gdb on Windows:
-
-
-
-
gdb support for Windows DLLs has improved lately, so it is
- now possible to debug Python extensions using a few
- tricks. Firstly, you will need an up-to-date gdb with support
- for minimal symbol extraction from a DLL. Any gdb from version 6
- onwards, or Cygwin gdb-20030214-1 and onwards should do. A
- suitable release will have a section in the gdb.info file under
- Configuration – Native – Cygwin Native –
- Non-debug DLL symbols. Refer to that info section for more
- details of the procedures outlined here.
-
-
Secondly, it seems necessary to set a breakpoint in the
- Python interpreter, rather than using ^C to break execution. A
- good place to set this breakpoint is PyOS_Readline, which will
- stop execution immediately before reading each interactive
- Python command. You have to let Python start once under the
- debugger, so that it loads its own DLL, before you can set the
- breakpoint:
-
-
-
-$ gdb python
-GNU gdb 2003-09-02-cvs (cygwin-special)
-[...]
-
-(gdb) run
-Starting program: /cygdrive/c/Python22/python.exe
-Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
-Type "help", "copyright", "credits" or "license" for more information.
->>> ^Z
-
-
-Program exited normally.
-(gdb) break *&PyOS_Readline
-Breakpoint 1 at 0x1e04eff0
-(gdb) run
-Starting program: /cygdrive/c/Python22/python.exe
-Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
-Type "help", "copyright", "credits" or "license" for more information.
-
-Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
- from /cygdrive/c/WINNT/system32/python22.dll
-(gdb) cont
-Continuing.
->>> from my_ext import *
-
-Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
- from /cygdrive/c/WINNT/system32/python22.dll
-(gdb) # my_ext now loaded (with any debugging symbols it contains)
-
-
-
-
Debugging extensions through Boost.Build
- If you are launching your extension module tests with Boost.Build using the
- boost-python-runtest rule, you can ask it to launch your
- debugger for you by adding "--debugger=debugger" to your bjam
- command-line:
-
-bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
-bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
-
- It can also be extremely useful to add the -d+2 option when
- you run your test, because Boost.Build will then show you the exact
- commands it uses to invoke it. This will invariably involve setting up
- PYTHONPATH and other important environment variables such as
- LD_LIBRARY_PATH which may be needed by your debugger in order to get
- things to work right.
-
-
-
Why doesn't my *= operator work?
-
-
- Q:I have exported my class to python, with many overloaded
- operators. it works fine for me except the*=
- operator. It always tells me "can't multiply sequence with non int
- type". If I usep1.__imul__(p2)instead of
- p1 *= p2, it successfully executes my code. What's
- wrong with me?
-
-
A: There's nothing wrong with you. This is a bug in Python
- 2.2. You can see the same effect in Pure Python (you can learn a lot
- about what's happening in Boost.Python by playing with new-style
- classes in Pure Python).
-
->>> class X(object):
-... def __imul__(self, x):
-... print 'imul'
-...
->>> x = X()
->>> x *= 1
-
- To cure this problem, all you need to do is upgrade your Python to
- version 2.2.1 or later.
-
-
-
-
Does Boost.Python work with Mac OS X?
-
- It is known to work under 10.2.8 and 10.3 using
- Apple's gcc 3.3 compiler:
-
gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)
- Under 10.2.8 get the August 2003 gcc update (free at
- http://connect.apple.com/).
- Under 10.3 get the Xcode Tools v1.0 (also free).
-
- Python 2.3 is required. The Python that ships with 10.3 is
- fine. Under 10.2.8 use these commands to install Python
- as a framework:
-
- The last command requires root privileges because the target
- directory is
- /Library/Frameworks/Python.framework/Versions/2.3.
- However, the installation does not interfere with the Python
- version that ships with 10.2.8.
-
- It is also crucial to increase the stacksize before
- starting compilations, e.g.:
-
limit stacksize 8192k
- If the stacksize is too small the build might crash with
- internal compiler errors.
-
- Sometimes Apple's compiler exhibits a bug by printing an error
- like the following while compiling a
- boost::python::class_<your_type>
- template instantiation:
-
.../inheritance.hpp:44: error: cannot
- dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
- ') to type `void*' (source type is not polymorphic)
-
- We do not know a general workaround, but if the definition of
- your_type can be modified the following was found
- to work in all cases encountered so far:
struct your_type
-{
- // before defining any member data
-#if defined(__MACH__) && defined(__APPLE_CC__) && __APPLE_CC__ == 1493
- bool dummy_;
-#endif
- // now your member data, e.g.
- double x;
- int j;
- // etc.
-};
- "I am wrapping a function that always returns a pointer to an
- already-held C++ object."
-
- One way to do that is to hijack the mechanisms used for wrapping a class
- with virtual functions. If you make a wrapper class with an initial
- PyObject* constructor argument and store that PyObject* as "self", you
- can get back to it by casting down to that wrapper type in a thin wrapper
- function. For example:
-
-class X { X(int); virtual ~X(); ... };
-X* f(); // known to return Xs that are managed by Python objects
-
-
-// wrapping code
-
-struct X_wrap : X
-{
- X_wrap(PyObject* self, int v) : self(self), X(v) {}
- PyObject* self;
-};
-
-handle<> f_wrap()
-{
- X_wrap* xw = dynamic_cast<X_wrap*>(f());
- assert(xw != 0);
- return handle<>(borrowed(xw->self));
-}
-
-...
-
-def("f", f_wrap());
-class_<X,X_wrap,boost::noncopyable>("X", init<int>())
- ...
- ;
-
- Of course, if X has no virtual functions you'll have to use
- static_cast instead of dynamic_cast with no
- runtime check that it's valid. This approach also only works if the
- X object was constructed from Python, because
- Xs constructed from C++ are of course never
- X_wrap objects.
-
-
Another approach to this requires you to change your C++ code a bit;
- if that's an option for you it might be a better way to go. work we've
- been meaning to get to anyway. When a shared_ptr<X> is
- converted from Python, the shared_ptr actually manages a reference to the
- containing Python object. When a shared_ptr<X> is converted back to
- Python, the library checks to see if it's one of those "Python object
- managers" and if so just returns the original Python object. So you could
- just write object(p) to get the Python object back. To
- exploit this you'd have to be able to change the C++ code you're wrapping
- so that it deals with shared_ptr instead of raw pointers.
-
-
There are other approaches too. The functions that receive the Python
- object that you eventually want to return could be wrapped with a thin
- wrapper that records the correspondence between the object address and
- its containing Python object, and you could have your f_wrap function
- look in that mapping to get the Python object out.
- Part of an API that I'm wrapping goes something like this:
-
-struct A {}; struct B { void add( A* ); }
-where B::add() takes ownership of the pointer passed to it.
-
-
-
However:
-
-a = mod.A()
-b = mod.B()
-b.add( a )
-del a
-del b
-# python interpreter crashes
-# later due to memory corruption.
-
-
-
Even binding the lifetime of a to b via
- with_custodian_and_ward doesn't prevent the python object a from
- ultimately trying to delete the object it's pointing to. Is there a way
- to accomplish a 'transfer-of-ownership' of a wrapped C++ object?
-
-
--Bruce Lowery
-
- Yes: Make sure the C++ object is held by auto_ptr:
-
-class_<A, std::auto_ptr<A> >("A")
- ...
- ;
-
- Then make a thin wrapper function which takes an auto_ptr parameter:
-
- Wrap that as B.add. Note that pointers returned via manage_new_object
- will also be held by auto_ptr, so this transfer-of-ownership
- will also work correctly.
-
-
-
error C2064: term does
- not evaluate to a function taking 2 arguments
- Niall Douglas provides these notes:
- If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue
- an error message like the following it is most likely due to a bug
- in the compiler:
-
boost\boost\python\detail\invoke.hpp(76):
-error C2064: term does not evaluate to a function taking 2 arguments"
- This message is triggered by code like the following:
-
A custom to_python converter (easy):
- custom_string_to_python_str
-
-
A custom lvalue converter (needs more code):
- custom_string_from_python_str
-
-
- The custom converters are registered in the global Boost.Python
- registry near the top of the module initialization function. Once
- flow control has passed through the registration code the automatic
- conversions from and to Python strings will work in any module
- imported in the same process.
-
-
Why is my automatic to-python conversion not being found?
- Niall Douglas provides these notes:
- If you define custom converters similar to the ones
- shown above the def_readonly() and def_readwrite()
- member functions provided by boost::python::class_ for
- direct access to your member data will not work as expected.
- This is because def_readonly("bar", &foo::bar) is
- equivalent to:
-
-
-
- In order to define return value policies compatible with the
- custom conversions replace def_readonly() and
- def_readwrite() by add_property(). E.g.:
-
-
Is Boost.Python thread-aware/compatible with multiple interpreters?
- Niall Douglas provides these notes:
- The quick answer to this is: no.
-
- The longer answer is that it can be patched to be so, but it's
- complex. You will need to add custom lock/unlock wrapping of every
- time your code enters Boost.Python (particularly every virtual
- function override) plus heavily modify
- boost/python/detail/invoke.hpp with custom unlock/lock
- wrapping of every time Boost.Python enters your code. You must
- furthermore take care to not unlock/lock when Boost.Python
- is invoking iterator changes via invoke.hpp.
-
- There is a patched invoke.hpp posted on the C++-SIG
- mailing list archives and you can find a real implementation of all
- the machinery necessary to fully implement this in the TnFOX
- project at this
- SourceForge project location.
- I spent the first week of February at the Python10 conference
- in Alexandria, VA. I'm including this experience report
- for two reasons: firstly, it documents where my time was
- used. Secondly, a public presence for Boost.Python and
- interaction between the Python and C++ communities is
- important to the future of Boost.Python, which in turn is
- important to the Kull Project.
-
-
Andy Koenig, of all people, was the keynote speaker of
- this year's opening plenary session. He presented his
- "impressions of a polyglot outsider", which
- studiously avoided any mention of C++ until the end of his
- talk, when he was asked about standardization. I was
- surprised to learn that the C++ community at large wanted a
- few more years before beginning but when ANSI accepted
- HP's request for a standard, the process was forced to
- start: it was a matter of participating or having
- standardization proceed without one's input. Andy managed
- to highlight very effectively the balance of strengths in
- Python, one of the most important being its support for
- extension via libraries. In many ways that makes Python a
- good analogue for C++ in the interpreted world
-
-
There were several kind mentions of the Boost.Python
- library from people who found it indispensable. I was
- particularly happy that Karl MacMillan, Michael Droettboom,
- and Ichiro Fujinaga from Johns Hopkins is using it to do OCR
- on a vast library of music notation, since in a previous life
- I was an author of music notation software. These guys are
- also drawing on Ullrich Koethe's VIGRA library for image
- manipulation (Ullrich has been a major contributor to
- Boost.Python). They also have a system for writing the
- Boost.Python wrapper code in C++ comments, which allows them
- to keep all of the code in one place. I've asked them to
- send me some information on that.
-
-
The development of Swig has been gaining momentum again
- (the basic description at
- www.boost.org/libs/python/doc/comparisons.html still
- applies). The talk given about it by David Beazly was very
- well-attended, and they appear to have quite a few users.
- Swig's strengths (coverage of many langauages) and
- weaknesses (incomplete C++ language support) haven't
- changed, although the C++ support seems to have improved
- considerably - they now claim to have a complete model of the
- C++ type system. It seems to be mostly geared at wrapping
- what Walter Landry calls "C-Tran": C++ code which
- traffics in built-in types with little use of abstraction.
- I'm not knocking that, either: I'm sure a lot of that
- code exists, so it's a valuable service. One feature Swig
- has which I'd like to steal is the ability to unwrap a
- single Python argument into multiple C++ arguments, for
- example, by converting a Python string into a pointer and
- length. When his talk was over, David approached me about a
- possible joint workshop on language binding, which sounds
- like a fun idea to me.
-
-
I spent some considerable time talking with Steven Knight,
- the leader of the Scons build tool effort. We had a lot to
- share with one another, and I gained a much better
- appreciation for many of the Scons design decisions. Scons
- seems to be concentrating on being the ultimate build system
- substrate, and Steve seemed to think that we were on the
- right track with our high-level design. We both hope that the
- Boost.Build V2 high-level architecture can eventually be
- ported to run on top of Scons.
-
-
They also have a highly-refined and successful development
- procedure which I'd like to emulate for Boost.Build V2.
- Among many other things they do, their source-control system
- automatically ensures that when you check in a new test, it
- is automatically run on the currently checked-in state of the
- code, and is expected to fail -- a relatively obvious good
- idea which I've never heard before.
-
-
Guido Van Rossum's "State of the Python
- Union" address was full of questions for the community
- about what should be done next, but the one idea Guido seemed
- to stress was that core language stability and continuing
- library development would be a good idea (sound familiar?) I
- mentioned the Boost model as a counterpoint to the idea of
- something like CPAN (the massive Perl library archives), and
- it seemed to generate some significant interest. I've
- offered to work with anyone from the Python community who
- wants to set up something like Boost.
-
-
There was some discussion of "string
- interpolation" (variable substitution in strings), and
- Guido mentioned that he had some thoughts about the
- strengths/weaknesses of Python's formatting interface. It
- might be useful for those working on formatting for boost to
- contact him and find out what he has to say.
-
-
Ka-Ping Yee demoed a Mailman discussion thread weaver.
- This tool weaves the various messages in a discussion thread
- into a single document so you can follow the entire
- conversation. Since we're looking very seriously at
- moving Boost to Mailman, this could be a really useful thing
- for us to have. If we do this, we'll move the yahoogroups
- discussions into the mailman archive so old discussions can
- be easily accessed in the same fashion.
-
-
And, just because it's cool, though perhaps not
- relevant: http://homepages.ulb.ac.be/~arigo/psyco/ is a
- promising effort to accelerate the execution of Python code
- to speeds approaching those of compiled languages. It
- reminded me a lot of Todd Veldhuizen's research into
- moving parts of C++ template compilation to runtime, only
- coming from the opposite end of things.
-
-
My first priority upon returning from Python10 was to get
- some documentation in place. After wasting an unfortunate
- amount of time looking at automatic documentation tools which
- don't quite work, I settled down to use Bill Kempf's
- HTML templates designed to be a boost standard. While they
- are working well, it is highly labor-intensive.
-
-
I decided to begin with the high-level reference material,
- as opposed to tutorial, narrative, or nitty-gritty details of
- the framework. It seemed more important to have a precise
- description of the way the commonly-used components work than
- to have examples in HTML (since we already have some test
- modules), and since the low-level details are much
- less-frequently needed by users it made sense for me to
- simply respond to support requests for the time being.
-
-
After completing approximately 60% of the high-level docs
- (currently checked in to libs/python/doc/v2), I found myself
- ready to start documenting the mechanisms for creating
- to-/from-python converters. This caused a dilemma: I had
- realized during the previous week that a much simpler,
- more-efficient, and easier-to-use implementation was
- possible, but I hadn't planned on implementing it right
- away, since what was already in place worked adequately. I
- had also received my first query on the C++-sig about how to
- write such a converter
-
-
Given the labor-intensive nature of documentation writing,
- I decided it would be a bad idea to document the conversion
- mechanism if I was just going to rewrite it. Often the best
- impetus for simplifying a design is the realization that
- understandably documenting its current state would be too
- difficult, and this was no exception.
-
-
There were two basic realizations involved here:
-
-
-
to_python conversion could be a one-step
- process, once an appropriate conversion function is found.
- This allows elimination of the separate indirect
- convertibility check
-
-
There are basically two categories of from_python
- conversions: those which lvalues stored within or held by
- the Python object (essentially extractions), like what
- happens when an instance of a C++ class exposed with class_
- is used as the target of a wrapped member function), and
- those in which a new rvalue gets created, as when a Python
- Float is converted to a C++
- complex<double> or a Python tuple is
- converted to a C++ std::vector<>. From
- the client side, there are two corresponding categories of
- conversion: those which demand an lvalue conversion and
- those which can accept an lvalue or an rvalue conversion.
-
- The latter realization allowed the following collapse, which
- considerably simplified things:
-
-
-
-
-
Target Type
-
-
Eligible Converters
-
-
-
T
-
-
T rvalue or lvalue
-
-
-
T const
-
-
-
T volatile
-
-
-
T const volatile
-
-
-
T const&
-
-
-
T const*
-
-
T lvalue
-
-
-
T volatile*
-
-
-
T const volatile*
-
-
-
T&
-
-
-
T volatile&
-
-
-
T const volatile&
-
-
-
T* const&
-
-
-
T const* const&
-
-
-
T volatile*const&
-
-
-
T const volatile*const&
-
-
- This job included the following additional enhancements:
-
-
-
Elimination of virtual functions, which cause object
- code bloat
-
-
Registration of a single converter function for all
- lvalue conversions, two for all rvalue conversions
-
-
Killed lots of unneeded code
-
-
Increased opacity of registry interface
-
-
Eliminated all need for decorated runtime type
- identifiers
-
-
Updated test modules to reflect new interface
-
-
Eliminated the need for users to worry about converter
- lifetime issues Additional Builtin Conversion Enhancements
-
-
Support for complex<float>,
- complex<double>, and complex<long double>
- conversions
-
-
Support for bool conversions
-
-
NULL pointers representable by None in Python
-
-
Support for conversion of Python classic classes to
- numeric types
-
msvc_typeinfo works around broken MS/Intel typeid()
- implementation
-
-
Many fixes and improvements to the type_traits library
- in order to work around compiler bugs and suppress warnings
-
-
Eliminated the need for explicit acquisition of
- converter registrations
-
-
Expanded constructor support to 6 arguments
-
-
Implemented generalized pointer lifetime support
-
-
Updated code generation for returning.hpp
-
-
Tracked down and fixed cycle GC bugs
-
-
Added comprehensive unit tests for destroy_reference,
- pointer_type_id, select_from_python, complex<T>,
- bool, and classic class instance conversions
-
Boost.Python supports docstrings with automatic
- appending of Pythonic and C++ signatures. This feature is implemented
- by class function_doc_signature_generator
- The class uses all of the overloads, supplied arg names and default values, as well as
- the user-defined docstrings, to generate documentation for a given function.
-
-
Classes
-
-
Class
- function_doc_signature_generator
-
-
- The class has only one public function which returns a list of strings documenting the
- overloads of a function.
-
<boost/python/handle.hpp> provides
- class template handle, a smart pointer for
- managing reference-counted Python objects.
-
-
Classes
-
-
Class template handle
-
-
handle is a smart pointer to a Python object type; it
- holds a pointer of type T*, where T is its template
- parameter. T must be either a type derived from
- PyObject or a POD type
- whose initial sizeof(PyObject) bytes are layout-compatible
- with PyObject. Use handle<> at the
- boundary between the Python/'C' API and high-level code; prefer object for a generalized
- interface to Python objects.
-
-
In this document, the term "upcast" refers to an
- operation which converts a pointer Y* to a base class
- pointer T* via static_cast<T*> if
- Y is derived from T, or via C-style cast
- (T*) if it is not. However, in the latter case the "upcast"
- is ill-formed if the initial sizeof(PyObject) bytes of
- Y are not layout-compatible with PyObject.
<boost/python/has_back_reference.hpp> defines the
- predicate metafunction has_back_reference<>, which can
- be specialized by the user to indicate that a wrapped class instance
- holds a PyObject* corresponding to a Python object.
-
-
Classes
-
-
Class template
- has_back_reference
-
-
A unary metafunction whose value is true iff its argument
- is a pointer_wrapper<>.
A "
- metafunction" that is inspected by Boost.Python to determine how
- wrapped classes can be constructed.
-
-
-
type::value is an integral constant convertible to bool
- of unspecified type.
-
-
Specializations may substitute a true-valued integral constant wrapper for
- type iff for each invocation of
- class_<WrappedClass>::def(init<
- type-sequence...>()) and the implicitly wrapped
- copy constructor (unless it is
- noncopyable), there exists a corresponding constructor
- WrappedClass::WrappedClass(PyObject*,
- type-sequence...). If such a specialization exists,
- the WrappedClass constructors will be called with a "back
- reference" pointer to the corresponding Python object whenever they are
- invoked from Python. The easiest way to provide this nested
-type
-
- is to
- derive the specialization from mpl::true_.
-
- The following Python session illustrates that x.self()
- returns the same Python object on which it is invoked, while
- y.self() must create a new Python object which refers to the
- same Y instance.
-
-
Python code
-
->>> from back_references import *
->>> x = X(1)
->>> x2 = x.self()
->>> x2 is x
-1
->>> (x.get(), x2.get())
-(1, 1)
->>> x.set(10)
->>> (x.get(), x2.get())
-(10, 10)
->>>
->>>
->>> y = Y(2)
->>> y2 = y.self()
->>> y2 is y
-0
->>> (y.get(), y2.get())
-(2, 2)
->>> y.set(20)
->>> (y.get(), y2.get())
-(20, 20)
-
- implicitly_convertible allows Boost.Python to implicitly
- take advantage of a C++ implicit or explicit conversion when matching
- Python objects to C++ argument types.
-
-
Functions
-
-
Function template
- implicitly_convertible
-
-template <class Source, class Target>
-void implicitly_convertible();
-
-
-
-
- implicitly_convertible template parameters
-
-
-
-
Parameter
-
-
Description
-
-
-
-
Source
-
-
The source type of the implicit conversion
-
-
-
-
Target
-
-
The target type of the implicit conversion
-
-
-
-
-
Requires: The declaration Target t(s);, where
- s is of type Source, is valid.
-
-
Effects: registers an rvalue from_python
- converter to Target which can succeed for any
- PyObject* p iff there exists any registered converter
- which can produce Source rvalues
-
-
Rationale: C++ users expect to be able to take advantage of
- the same sort of interoperability in Python as they do in C++.
- Indexing is a Boost Python facility for easy exportation of indexable
- C++ containers to Python. Indexable containers are containers that
- allow random access through the operator[] (e.g. std::vector).
-
-
- While Boost Python has all the facilities needed to expose indexable
- C++ containers such as the ubiquitous std::vector to Python, the
- procedure is not as straightforward as we'd like it to be. Python
- containers do not map easily to C++ containers. Emulating Python
- containers in C++ (see Python Reference Manual, Emulating
- container types) using Boost Python is non trivial. There are a lot
- of issues to consider before we can map a C++ container to Python.
- These involve implementing wrapper functions for the methods
- __len__, __getitem__,
- __setitem__, __delitem__,
- __iter__ and __contains.
-
-
- The goals:
-
-
-
-
- Make indexable C++ containers behave exactly as one would expect a
- Python container to behave.
-
-
-
- Provide default reference semantics for container element indexing
- (__getitem__) such that c[i] can be mutable.
- Require:
-
-
- val = c[i]
- c[i].m()
- val == c[i]
-
-
where m is a non-const (mutating) member function
- (method).
-
-
- Return safe references from __getitem__ such that subsequent
- adds and deletes to and from the container will not result in
- dangling references (will not crash Python).
-
- The indexing_suite class is the base class for the
- management of C++ containers intended to be integrated to Python. The
- objective is make a C++ container look and feel and behave exactly as
- we'd expect a Python container. The class automatically wraps these
- special Python methods (taken from the Python reference: Emulating
- container types):
-
- Called to implement the built-in function len() Should return
- the length of the object, an integer >= 0. Also,
- an object that doesn't define a __nonzero__() method and whose __len__() method returns zero is considered to be
- false in a Boolean context.
-
- Called to implement evaluation of
- self[key]. For sequence types,
- the accepted keys should be integers and slice
- objects. Note that the special
- interpretation of negative indexes (if the class wishes to
- emulate a sequence type) is up to the __getitem__() method. If key is of
- an inappropriate type, TypeError
- may be raised; if of a value outside the set of indexes for
- the sequence (after any special interpretation of negative
- values), IndexError should be
- raised. Note:
- for loops expect that an IndexError will be raised for illegal
- indexes to allow proper detection of the end of the
- sequence.
-
- Called to implement assignment to
- self[key]. Same note as for
- __getitem__(). This should only be
- implemented for mappings if the objects support changes to the
- values for keys, or if new keys can be added, or for sequences if
- elements can be replaced. The same exceptions should be raised
- for improper key values as for the __getitem__() method.
-
- Called to implement deletion of
- self[key]. Same note as for
- __getitem__(). This should only be
- implemented for mappings if the objects support removal of keys,
- or for sequences if elements can be removed from the sequence.
- The same exceptions should be raised for improper key
- values as for the __getitem__() method.
-
- This method is called when an iterator is required for a
- container. This method should return a new iterator object that
- can iterate over all the objects in the container. For mappings,
- it should iterate over the keys of the container, and should also
- be made available as the method iterkeys().
-
- Iterator objects also need to implement this method; they are
- required to return themselves. For more information on iterator
- objects, see ``Iterator
- Types'' in the Python Library Reference.
-
- Called to implement membership test operators. Should return true
- if item is in self, false otherwise. For
- mapping objects, this should consider the keys of the mapping
- rather than the values or the key-item pairs.
-
-
-
-
-
-
indexing_suite sub-classes
-
- The indexing_suite is not meant to be used as is. A couple of
- policy functions must be supplied by subclasses of
- indexing_suite. However, a set of indexing_suite
- subclasses for the standard indexable STL containers will be provided,
- In most cases, we can simply use the available predefined suites. In
- some cases, we can refine the predefined suites to suit our needs.
-
- The vector_indexing_suite class is a predefined
- indexing_suite derived class designed to wrap
- std::vector (and std::vector like [i.e. a class with
- std::vector interface]) classes. It provides all the policies required by the
- indexing_suite.
-
-
- Example usage:
-
-
- class X {...};
- ...
-
- class_<std::vector<X> >("XVec")
- .def(vector_indexing_suite<std::vector<X> >())
- ;
-
The map_indexing_suite class is a predefined indexing_suite derived class designed to wrap std::map (and std::map like [i.e. a class with std::map interface]) classes. It provides all the policies required by the indexing_suite.
-
Example usage:
-
- class X {...};
- ...
-
- class_<std::map<X> >("XMap")
- .def(map_indexing_suite<std::map<X> >())
- ;
-
-
By default indexed elements are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter. XMap is now a full-fledged Python container (see the example in full, along with its python test).
-
-
- indexing_suite class
-
indexing_suite<
- class Container
- , class DerivedPolicies
- ,
- bool NoProxy
- ,
- bool NoSlice
- , class Data
- , class Index
- , class Key
-
-
-
- Template Parameter
-
-
- Requirements
-
-
- Semantics
-
-
- Default
-
-
-
-
- Container
-
-
- A class type
-
-
- The container type to be wrapped to Python.
-
-
-
-
-
-
-
- DerivedPolicies
-
-
- A subclass of indexing_suite
-
-
- Derived classes provide the policy hooks. See DerivedPolicies below.
-
-
-
-
-
-
-
NoProxy
-
A boolean
-
By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter.
-
false
-
-
-
- NoSlice
-
-
- A boolean
-
-
- Do not allow slicing.
-
- false
-
-
-
-
- Data
-
-
-
-
-
- The container's data type.
-
-
- Container::value_type
-
-
-
-
Index
-
-
The container's index type.
-
Container::size_type
-
-
-
- Key
-
-
-
-
-
- The container's key type.
-
-
- Container::value_type
-
-
-
-
- template < class Container
- , class DerivedPolicies
- , bool NoProxy = false , bool NoSlice = false
- , class Data = typename Container::value_type
- , class Index = typename Container::size_type
- , class Key = typename Container::value_type
- > class indexing_suite
- : unspecified
- {
- public:
-
- indexing_suite(); // default constructor
- }
-
-
- DerivedPolicies
-
-
-
- Derived classes provide the hooks needed by
- the indexing_suite:
-
- Most of these policies are self explanatory. However,
- convert_index and
- adjust_index deserve some explanation.
-
-
- convert_index converts a Python index into
- a C++ index that the container can handle. For instance, negative
- indexes in Python, by convention, start counting from the right(e.g.
- C[-1] indexes the rightmost element in C).
- convert_index should handle the necessary
- conversion for the C++ container (e.g. convert -1 to
- C.size()-1). convert_index should
- also be able to convert the type of the index (A dynamic Python type)
- to the actual type that the C++ container expects.
-
-
- When a container expands or contracts, held indexes to its elements
- must be adjusted to follow the movement of data. For instance, if we
- erase 3 elements, starting from index 0 from a 5 element vector, what
- used to be at index 4 will now be at index 1:
-
-
- [a][b][c][d][e] ---> [d][e]
- ^ ^
- 4 1
-
-
- adjust_index takes care of the adjustment.
- Given a current index, the function should return the adjusted index
- when data in the container at index from..to is
- replaced by len elements.
-
-
-
-
-
- vector_indexing_suite class
-
-
- Class template
- vector_indexing_suite<
- class Container
- , bool NoProxy
- , class DerivedPolicies>
-
-
-
-
- Template Parameter
-
-
- Requirements
-
-
- Semantics
-
-
- Default
-
-
-
-
- Container
-
-
- A class type
-
-
- The container type to be wrapped to Python.
-
-
-
-
-
-
-
- NoProxy
-
-
- A boolean
-
-
- By default indexed elements have Python reference semantics and
- are returned by proxy. This can be disabled by supplying
- true in the NoProxy template parameter.
-
-
- false
-
-
-
-
- DerivedPolicies
-
-
- A subclass of indexing_suite
-
-
- The vector_indexing_suite may still be derived to
- further tweak any of the predefined policies. Static polymorphism
- through CRTP (James Coplien. "Curiously Recurring Template
- Pattern". C++ Report, Feb. 1995) enables the base
- indexing_suite class to call policy function of the most
- derived class
-
-
-
-
-
-
-
- template < class Container, bool NoProxy = false, class DerivedPolicies = unspecified_default class vector_indexing_suite : unspecified_base { public:
Class template
- map_indexing_suite<
- class Container
- , bool NoProxy
- , class DerivedPolicies>
-
-
-
Template Parameter
-
-
Requirements
-
Semantics
-
Default
-
-
-
Container
-
A class type
-
The container type to be wrapped to Python.
-
-
-
-
NoProxy
-
A boolean
-
By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter.
-
false
-
-
-
DerivedPolicies
-
A subclass of indexing_suite
-
The vector_indexing_suite may still be derived to further tweak any of the predefined policies. Static polymorphism through CRTP (James Coplien. "Curiously Recurring Template Pattern". C++ Report, Feb. 1995) enables the base indexing_suite class to call policy function of the most derived class
-
-
-
-
- template < class Container, bool NoProxy = false, class DerivedPolicies = unspecified_default class map_indexing_suite : unspecified_base { public:
- An init-expression is used to describe a family of
- __init__ methods to be generated for an extension class, and
- the result has the following properties:
-
-
-
-
docstring: An ntbs
- whose value will bound to the method's __doc__
- attribute
-
-
keywords: A keyword-expression which will be
- used to name (a trailing subsequence of) the arguments to the
- generated __init__ function(s).
-
-
call policies: An instance of a model of CallPolicies.
-
-
argument types: An MPL sequence of C++ argument types
- which will be used to construct the wrapped C++ object. An init
- expression has one or more
- valid prefixes which are given by a sequence of
- prefixes of its argument types.
A MPL sequence which
- can be used to specify a family of one or more __init__
- functions. Only the last Ti supplied
- may be an instantiation of optional<...>.
Requires: If supplied, doc is an ntbs. If supplied, kw is the
- result of a
-
-
Effects: The result is an init-expression whose
- docstring is doc and whose keywords are
- a reference to kw. If the first form is used, the
- resulting expression's keywords are empty. The expression's
- call policies are an instance of default_call_policies.
- If Tn is optional<U1, U2,...
- Um>, the
- expression's valid prefixes are given by:
Effects: Returns a new init-expression with all the same
- properties as the init object except that its call
- policies are replaced by a reference to
- policies.
<boost/python/instance_holder.hpp> provides
- class instance_holder, the base class for types
- which hold C++ instances of wrapped classes.
-
-
Classes
-
-
Class instance_holder
-
-
instance_holder is an abstract base class whose
- concrete derived classes hold C++ class instances within their
- Python object wrappers. To allow multiple inheritance in Python
- from C++ class wrappers, each such Python object contains a chain
- of instance_holders. When an __init__
- function for a wrapped C++ class is invoked, a new
- instance_holder instance is created and installed in
- the Python object using its install()
- function. Each concrete class derived from
- instance_holder must provide a holds()
- implementation which allows Boost.Python to query it for the
- type(s) it is holding. In order to support the held type's wrapped
- constructor(s), the class must also provide constructors that can
- accept an initial PyObject* argument referring to the
- owning Python object, and which forward the rest of their
- arguments to the constructor of the held type. The initial
- argument is needed to enable virtual function overriding in
- Python, and may be ignored, depending on the specific
- instance_holder subclass.
-
-
<boost/python/iterator.hpp> provides types and
- functions for creating Python
- iterators from C++ Containers and Iterators. Note
- that if your class_ supports random-access iterators,
- implementing __getitem__
- (also known as the Sequence Protocol) may serve you better than using
- this facility: Python will automatically create an iterator type for you
- (see iter()),
- and each access can be range-checked, leaving no possiblity of accessing
- through an invalidated C++ iterator.
-
-
Classes
-
-
Class Template iterator
-
-
Instances of iterator<C,P> hold a reference to a
- callable Python object which, when invoked from Python, expects a single
- argument c convertible to C and creates a
- Python iterator that traverses [c.begin(),
- c.end()). The optional CallPoliciesP can be used to
- control how elements are returned during iteration.
-
-
In the table below, c is an instance of
- Container.
The result will convert its argument to c and call
- c.begin() and c.end() to acquire iterators.
- To invoke Container's const
- begin() and end() functions, make it
- const.
Postconditions:this->get() points to a
- Python callable object which creates a Python iterator as described
- above.
-
-
Rationale: Provides an easy way to create iterators for the
- common case where a C++ class being wrapped provides
- begin() and end().
-
-
-
-
Class Template
- iterators
-
-
A utility class template which provides a way to reliably call its
- argument's begin() and end() member functions.
- Note that there is no portable way to take the address of a member
- function of a C++ standard library container, so
- iterators<> can be particularly helpful when wrapping
- them.
-
-
In the table below, x is an instance of
- C.
-
-
-
-
Required Valid Expression
-
-
Type
-
-
-
-
x.begin()
-
-
Convertible to C::const_iterator if C
- is a const type; convertible to C::iterator
- otherwise.
-
-
-
-
x.end()
-
-
Convertible to C::const_iterator if C
- is a const type; convertible to C::iterator
- otherwise.
-template <class NextPolicies, class Target, class Accessor1, class Accessor2>
-object range(Accessor1 start, Accessor2 finish);
-
-template <class NextPolicies, class Accessor1, class Accessor2>
-object range(Accessor1 start, Accessor2 finish);
-
-template <class Accessor1, class Accessor2>
-object range(Accessor1 start, Accessor2 finish);
-
-
-
-
Requires:NextPolicies is a
- default-constructible model of CallPolicies.
-
-
Effects:
-
-
-
-
The first form creates a Python callable object which, when
- invoked, converts its argument to a Target object
- x, and creates a Python iterator which traverses
- [bind(start,_1)(x), bind(finish,_1)(x)),
- applying NextPolicies to the iterator's
- next() function.
-
-
The second form is identical to the first, except that
- Target is deduced from Accessor1 as
- follows:
-
-
-
-
If Accessor1 is a function type,
- Target is the type of its first argument.
-
-
If Accessor1 is a data member pointer of the
- form R (T::*), Target is
- identical to T.
-
-
If Accessor1 is a member function pointer of
- the form
- R (T::*)(arguments...)
- cv-opt, where cv-opt is an optional
- cv-qualifier, Target is identical to
- T.
-
-
-
-
The third form is identical to the second, except that
- NextPolicies is an unspecified model of CallPolicies which
- always makes a copy of the result of deferencing the underlying C++
- iterator
-
-
-
-
Rationale: The use of boost::bind() allows C++ iterators
- to be accessed through functions, member functions or data member
- pointers. Customization of NextPolicies (e.g. using
- return_internal_reference)
- is useful when it is expensive to copy sequence elements of a wrapped
- class type. Customization of Target is useful when
- Accessor1 is a function object, or when a base class of
- the intended target type would otherwise be deduced.
Exposes the mapping
- protocol of Python's built-in list type. The semantics
- of the constructors and member functions defined below can be fully
- understood by reading the TypeWrapper concept
- definition. Since list is publicly derived from object, the public object
- interface applies to list instances as well.
Exposes the numeric type
- protocol of Python's built-in long type. The semantics
- of the constructors and member functions defined below can be fully
- understood by reading the TypeWrapper concept
- definition. Since long_ is publicly derived from object, the public object
- interface applies to long_ instances as well.
-
-
Class long_
- synopsis
-
-namespace boost { namespace python
-{
- class long_ : public object
- {
- public:
- long_(); // new long_
-
- template <class T>
- explicit long_(T const& rhs);
-
- template <class T, class U>
- long_(T const& rhs, U const& base);
- };
-}}
-
-
-
Example
-
-namespace python = boost::python;
-
-// compute a factorial without overflowing
-python::long_ fact(long n)
-{
- if (n == 0)
- return python::long_(1);
- else
- return n * fact(n - 1);
-}
-
- <boost/python/lvalue_from_pytype.hpp> supplies a
- facility for extracting C++ objects from within Python instances of a
- given type. This is typically useful for dealing with "traditional"
- Python extension types.
-
-
Classes
-
-
Class template
- lvalue_from_pytype
-
-
Class template lvalue_from_pytype will register
- from_python converters which, given an object of the given Python type,
- can extract references and pointers to a particular C++ type. Its
- template arguments are:
-
-
-
- lvalue_from_pytype Requirements
- In the table below, x denotes an object of type
- PythonObject&
-
-
-
-
Parameter
-
-
Requirements
-
-
Semantics
-
-
-
-
Extractor
-
-
a model of Extractor whose execute
- function returns a reference type.
-
-
Extracts the lvalue from the Python object once its type has been
- confirmed
Effects: Registers converters which can convert Python
- objects of the given type to lvalues of the type returned by
- Extractor::execute.
-
-
-
Class template
- extract_identity
-
-
extract_identity is a model of Extractor which can be used in the
- common case where the C++ type to be extracted is the same as the Python
- object type.
Class template
- extract_identity static functions
-
-InstanceType& execute(InstanceType& c);
-
-
-
-
Returns:c
-
-
-
Class template
- extract_member
-
-
extract_member is a model of Extractor which can be used in the
- common case in the common case where the C++ type to be extracted is a
- member of the Python object.
- This example presumes that someone has implemented the standard noddy example
- module from the Python documentation, and we want to build a module
- which manipulates Noddys. Since
- noddy_NoddyObject is so simple that it carries no
- interesting information, the example is a bit contrived: it assumes you
- want to keep track of one particular object for some reason. This module
- would have to be dynamically linked to the module which defines
- noddy_NoddyType.
-
-
make_function() and
- make_constructor() are
- the functions used internally by def() and class_<>::def() to produce Python
- callable objects which wrap C++ functions and member functions.
-
-
Functions
-
-template <class F>
-object make_function(F f)
-
-template <class F, class Policies>
-object make_function(F f, Policies const& policies)
-
-template <class F, class Policies, class KeywordsOrSignature>
-object make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
-
-template <class F, class Policies, class Keywords, class Signature>
-object make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
-
-
-
-
Requires:F is a function pointer or member
- function pointer type. If policies are supplied, it must
- be a model of CallPolicies. If
- kewords are supplied, it must be the result of a keyword-expression
- specifying no more arguments than the arity of f.
-
-
Effects: Creates a Python callable object which, when called
- from Python, converts its arguments to C++ and calls f. If
- F is a pointer-to-member-function type, the target
- object of the function call (*this) will be taken
- from the first Python argument, and subsequent Python arguments
- will be used as the arguments
- to f.
-
If policies are supplied, it
- will be applied to the function as described here.
-
If keywords are
- supplied, the keywords will be applied in order to the final
- arguments of the resulting function.
-
If Signature
- is supplied, it should be an instance of an MPL front-extensible
- sequence representing the function's return type followed by
- its argument types. Pass a Signature when wrapping
- function object types whose signatures can't be deduced, or when
- you wish to override the types which will be passed to the
- wrapped function.
-
-
-
Returns: An instance of object which holds the new Python
- callable object.
-
-
Caveats: An argument of pointer type may
- be 0 if None is passed from Python.
- An argument type which is a constant reference may refer to a
- temporary which was created from the Python object for just the
- duration of the call to the wrapped function, for example
- a std::vector conjured up by the conversion process
- from a Python list. Use a non-const reference
- argument when a persistent lvalue is required.
-
-
-
-template <class F>
-object make_constructor(F f)
-
-template <class F, class Policies>
-object make_constructor(F f, Policies const& policies)
-
-template <class F, class Policies, class KeywordsOrSignature>
-object make_constructor(F f, Policies const& policies, KeywordsOrSignature const& ks)
-
-template <class F, class Policies, class Keywords, class Signature>
-object make_constructor(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
-
-
-
-
Requires:F is a
- function pointer type. If policies are supplied, it must
- be a model of CallPolicies. If
- kewords are supplied, it must be the result of a keyword-expression
- specifying no more arguments than the arity of f.
-
-
Effects: Creates a Python callable object which, when called
- from Python, converts its arguments to C++ and calls f.
-
-
Returns: An instance of object which holds the new Python
- callable object.
-
-
-
Example
-
-
C++ function exposed below returns a callable object wrapping one of
- two functions.
manage_new_object is a model of ResultConverterGenerator
- which can be used to wrap C++ functions which return a pointer to an
- object allocated with a new-expression, and expect the caller to
- take responsibility for deleting that object.
- Boost.Python modules should be initialized with
-
-BOOST_PYTHON_MODULE(name)
-{
- ...
-}
-
-
-This macro generates two functions in the scope where it is used:
-extern "C" void initname(),
-and void init_module_name(), whose body must
-follow the macro invocation. init_name passes
-init_module_name to handle_exception() so
-that any C++ exceptions generated are safely processeed. During the
-body of init_name, the current scope refers to the module
-being initialized.
-
-
Provides access to the array types of Numerical Python's Numeric and NumArray modules. With
- the exception of the functions documented below, the semantics of the constructors and
- member functions defined below can be fully understood by reading the
- TypeWrapper concept
- definition. Since array is publicly derived from
- object, the public
- object interface applies to array instances as well.
-
-
The default behavior is
- to use numarray.NDArray as the associated Python type if the
- numarray module is installed in the default location.
- Otherwise it falls back to use Numeric.ArrayType. If neither
- extension module is installed, overloads of wrapped C++ functions with
- numeric::array parameters will never be matched, and other
- attempted uses of numeric::array will raise an appropriate Python exception. The
- associated Python type can be set manually using the set_module_and_type(...) static
- function.
-object factory();
-template <class Sequence>
-object factory(Sequence const&);
-template <class Sequence, class Typecode>
-object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
-template <class Sequence, class Typecode, class Type>
-object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
-template <class Sequence, class Typecode, class Type, class Shape>
-object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
-
These functions map to the underlying array type's array()
-function family. They are not called "array" because of the C++
-limitation that you can't define a member function with the same name as its
-enclosing class.
-
Requires:package_path and
- type_name, if supplied, is an ntbs.
-
-
Effects: The first form sets the package path of the module
- that supplies the type named by type_name to
- package_path. The second form restores the default search behavior. The associated Python type
- will be searched for only the first time it is needed, and thereafter the
- first time it is needed after an invocation of
- set_module_and_type.
-
-
-static std::string get_module_name()
-
-
-
-
Effects: Returns the name of the module containing the class
- that will be held by new numeric::array instances.
-
-
-
Example
-
-#include <boost/python/numeric.hpp>
-#include <boost/python/tuple.hpp>
-
-// sets the first element in a 2d numeric array
-void set_first_element(numeric::array& y, double value)
-{
- y[make_tuple(0,0)] = value;
-}
-
Exposes the generic Python object wrapper class object,
- and related classes. In order to avoid some potenential problems with
- argument-dependent lookup and the generalized operators defined on
- object, all these facilities are defined in
- namespace boost::python::api, and object
- is imported into namespace boost::python with a
- using-declaration.
This is the base class of object and its
- proxy template used to supply common interface: member
- functions, and operators which must be defined within the class body. Its
- template parameter U is expected to be a class derived from
- object_operators<U>. In practice users should never
- use this class directly, but it is documented here because it supplies
- important interface to object and its proxies.
Effects: accesses the item of *this indicated
- by key.
-
-
Returns: a proxy object which binds
- object(*static_cast<U*>(this)) as its target, and
- object(key) as its key.
-
-
-template <class T, class V>
-proxy<const_object_slice> slice(T const& start; start, V const& finish) const
-template <class T, class V>
-proxy<object_slice> slice(T const& start; start, V const& finish);
-
-
-
-
Effects: accesses the slice of *this indicated
- by std::make_pair(object(start), object(finish)).
-
-
Returns: a proxy object which binds
- object(*static_cast<U*>(this)) as its target, and
- std::make_pair(object(start), object(finish)) as its
- key.
-
-
-
-
Class object
-
-
The intention is that object acts as much like a
- Python variable as possible. Thus expressions you'd expect to work
- in Python should generally work in the same way from C++. Most of
- object's interface is provided by its base class
- object_operators<object>,
- and the free functions defined in this
- header.
-
Effects: converts x to python and manages a
- reference to it.
-
-
Throws:error_already_set and sets a Python
- TypeError exception if no such conversion is
- possible.
-
-
-~object();
-
-
-
-
Effects: decrements the reference count of the
- internally-held object.
-
-
-
Class object
- modifiers
-
-object& operator=(object const& rhs);
-
-
-
-
Effects: increments the reference count of the object held
- by rhs and decrements the reference count of the object
- held by *this.
-
-
-
Class object
- observers
-
-PyObject* ptr() const;
-
-
-
-
Returns: a pointer to the internally-held Python
- object.
-
-
-
-bool is_none() const;
-
-
-
-
Returns: result of (ptr() == Py_None)
-
-
-
-
Class template proxy
-
-
This template is instantiated with various Policies described in this
- document in order to implement attribute, item, and slice access for
- object. It stores an object of type
- Policies::key_type.
Registers the instance as a
- lvalue_from_pytype
- converter from Python objects into opaque pointers.
-
The Python Objects created are named after the type pointed to
- by the opaque pointer being wrapped.
-
Registers the instance as a
- to_python_converter
- from opaque pointers to Python objects.
-
-
If there is already an instance registered by another module, this
- instance doesn't try to register again in order to avoid warnings
- about multiple registrations.
-
-
Note
-
Normally only a single instance of this class is created for every
- Pointee.
<boost/python/operators.hpp> provides types and
- functions for automatically generating Python special methods
- from the corresponding C++ constructs. Most of these constructs are
- operator expressions, hence the name. To use the facility, substitute the
- self object for an object of the
- class type being wrapped in the expression to be exposed, and pass the
- result to class_<>::def(). Much of
- what is exposed in this header should be considered part of the
- implementation, so is not documented in detail here.
-
-
Classes
-
-
Class self_ns::self_t
-
-
self_ns::self_t is the actual type of the self object. The library isolates
- self_t in its own namespace, self_ns, in order
- to prevent the generalized operator templates which operate on it from
- being found by argument-dependent lookup in other contexts. This should
- be considered an implementation detail, since users should never have to
- mention self_t directly.
-
-
Class self_ns::self_t
- synopsis
-
-namespace boost { namespace python { namespace self_ns {
-{
- unspecified-type-declaration self_t;
-
- // inplace operators
- template <class T> operator_<unspecified> operator+=(self_t, T);
- template <class T> operator_<unspecified> operator-=(self_t, T);
- template <class T> operator_<unspecified> operator*=(self_t, T);
- template <class T> operator_<unspecified> operator/=(self_t, T);
- template <class T> operator_<unspecified> operator%=(self_t, T);
- template <class T> operator_<unspecified> operator>>=(self_t, T);
- template <class T> operator_<unspecified> operator<<=(self_t, T);
- template <class T> operator_<unspecified> operator&=(self_t, T);
- template <class T> operator_<unspecified> operator^=(self_t, T);
- template <class T> operator_<unspecified> operator|=(self_t, T);
-
- // comparisons
- template <class L, class R> operator_<unspecified> operator==(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator!=(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator<(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator>(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator<=(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator>=(L const&, R const&);
-
- // non-member operations
- template <class L, class R> operator_<unspecified> operator+(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator-(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator*(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator/(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator%(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator>>(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator<<(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator&(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator^(L const&, R const&);
- template <class L, class R> operator_<unspecified> operator|(L const&, R const&);
- template <class L, class R> operator_<unspecified> pow(L const&, R const&);
-
- // unary operations
- operator_<unspecified> operator-(self_t);
- operator_<unspecified> operator+(self_t);
- operator_<unspecified> operator~(self_t);
- operator_<unspecified> operator!(self_t);
-
- // value operations
- operator_<unspecified> int_(self_t);
- operator_<unspecified> long_(self_t);
- operator_<unspecified> float_(self_t);
- operator_<unspecified> complex_(self_t);
- operator_<unspecified> str(self_t);
-
- operator_<unspecified> repr(self_t);
-
-}}};
-
- The tables below describe the methods generated when the results of the
- expressions described are passed as arguments to class_<>::def().
- x is an object of the class type being wrapped.
-
-
Class self_t inplace
- operators
- In the table below, If r is an object of type
- other<T>,
- y is an object of type T; otherwise,
- y is an object of the same type as
- r.
-
-
-
-
C++ Expression
-
-
Python Method Name
-
-
C++ Implementation
-
-
-
-
self += r
-
-
__iadd__
-
-
x += y
-
-
-
-
self -= r
-
-
__isub__
-
-
x -= y
-
-
-
-
self *= r
-
-
__imul__
-
-
x *= y
-
-
-
-
self /= r
-
-
__idiv__
-
-
x /= y
-
-
-
-
self %= r
-
-
__imod__
-
-
x %= y
-
-
-
-
self >>= r
-
-
__irshift__
-
-
x >>= y
-
-
-
-
self <<= r
-
-
__ilshift__
-
-
x <<= y
-
-
-
-
self &= r
-
-
__iand__
-
-
x &= y
-
-
-
-
self ^= r
-
-
__ixor__
-
-
x ^= y
-
-
-
-
self |= r
-
-
__ior__
-
-
x |= y
-
-
-
-
Class self_t
- comparison functions
- In the tables below, if r is of type self_t, y is an object of
- the same type as x;
- if l or r is an object of type
- other<T>,
- y is an object of type T;
- otherwise, y is an object of the same type as
- l or r.
- l is never of type self_t.
-
-
The column of Python Expressions illustrates the expressions
- that will be supported in Python for objects convertible to the types of
- x and y. The secondary operation arises due to
- Python's reflection
- rules for rich comparison operators, and are only used when the
- corresponding operation is not defined as a method of the y
- object.
-
-
-
-
C++ Expression
-
-
Python Method Name
-
-
C++ Implementation
-
-
Python Expressions
- (primary, secondary)
-
-
-
-
self == r
-
-
__eq__
-
-
x == y
-
-
x == y, y == x
-
-
-
-
l == self
-
-
__eq__
-
-
y == x
-
-
y == x, x == y
-
-
-
-
self != r
-
-
__ne__
-
-
x != y
-
-
x != y, y != x
-
-
-
-
l != self
-
-
__ne__
-
-
y != x
-
-
y != x, x != y
-
-
-
-
self < r
-
-
__lt__
-
-
x < y
-
-
x < y, y > x
-
-
-
-
l < self
-
-
__gt__
-
-
y < x
-
-
y > x, x < y
-
-
-
-
self > r
-
-
__gt__
-
-
x > y
-
-
x > y, y < x
-
-
-
-
l > self
-
-
__lt__
-
-
y > x
-
-
y < x, x > y
-
-
-
-
self <= r
-
-
__le__
-
-
x <= y
-
-
x <= y, y >= x
-
-
-
-
l <= self
-
-
__ge__
-
-
y <= x
-
-
y >= x, x <= y
-
-
-
-
self >= r
-
-
__ge__
-
-
x >= y
-
-
x >= y, y <= x
-
-
-
-
l >= self
-
-
__le__
-
-
y >= x
-
-
y <= x, x >= y
-
-
-
-
Class self_t non-member
- operations
- The operations whose names begin with "__r" below will only
- be called if the left-hand operand does not already support the given
- operation, as described here.
-
-
-
Instances of other<T> can be used in operator
- expressions with self; the result is equivalent
- to the same expression with a T object in place of
- other<T>. Use other<T> to prevent
- construction of a T object in case it is heavyweight, when
- no constructor is available, or simply for clarity.
Instantiations of detail::operator_<> are used as
- the return type of operator expressions involving self. This should be considered an implementation
- detail and is only documented here as a way of showing how the result of
- self-expressions match calls to class_<>::def().
Defines facilities for generating families of overloaded Python
- functions and extension class methods from C++ functions and
- member functions with default arguments, or from similar families
- of C++ overloads
-
-
overload-dispatch-expressions
-
-
- An overload-dispatch-expression is used to describe a
- family of overloaded methods to be generated for an extension
- class. It has the following properties:
-
-
-
-
docstring: An ntbs
- whose value will bound to the methods' __doc__
- attribute
-
-
keywords: A keyword-expression which
- will be used to name (a trailing subsequence of) the arguments
- to the generated methods.
-
-
call policies: An instance of some type which models CallPolicies.
-
-
minimum arity
- The minimum number of arguments to be accepted by a generated
- method overload.
-
-
maximum arity
- The maximum number of arguments to be accepted by a generated
- method overload.
-
-
-
-
OverloadDispatcher Concept
-
- An OverloadDispatcher X is a class which has a
- minimum arity and a maximum arity, and for which
- the following following are valid overload-dispatch-expressions,
- with the same minimum and maximum arity as the OverloadDispatcher.
-
-
If policies are supplied, it must be an instance of a
-type which models CallPolicies, and
-will be used as the result's call policies. Otherwise the result's
-call policies will be an instance of default_call_policies.
-
-
If docstring is supplied it must be an ntbs, and will be used as the result's docstring. Otherwise the result has an empty docstring.
-
-
If keywords is supplied it must be the result of a keyword-expression
- whose length is no greater than X's maximum
- arity, and will be used as the result's keywords. Otherwise
- the result's keywords will be empty.
-
- Expands to the definition of an OverloadDispatcher called
- name in the current scope which can be used to
- generate the following function invocation:
-
-
- Expands to the definition of an OverloadDispatcher called
- name in the current scope which can be used to
- generate the following function invocation:
-
-x.member_name(a1, a2,...ai);
-
-
- for all min_args <= i <=
- max_args, where x is a reference to an
- object of class type.
-
-
Pickle is a Python module for object
- serialization, also known as persistence, marshalling, or flattening.
-
-
It is often necessary to save and restore the contents of an object to
- a file. One approach to this problem is to write a pair of functions that
- read and write data from a file in a special format. A powerful
- alternative approach is to use Python's pickle module. Exploiting
- Python's ability for introspection, the pickle module recursively
- converts nearly arbitrary Python objects into a stream of bytes that can
- be written to a file.
-
-
The Boost Python Library supports the pickle module through the
- interface as described in detail in the Python Library
- Reference for pickle. This interface involves the special methods
- __getinitargs__, __getstate__ and __setstate__
- as described in the following. Note that Boost.Python is also fully
- compatible with Python's cPickle module.
-
-
-
The Boost.Python Pickle Interface
At the user level, the
- Boost.Python pickle interface involves three special methods:
-
-
-
__getinitargs__
-
-
- When an instance of a Boost.Python extension class is pickled, the
- pickler tests if the instance has a __getinitargs__ method.
- This method must return a Python tuple (it is most convenient to use
- a boost::python::tuple). When the instance is restored by the
- unpickler, the contents of this tuple are used as the arguments for
- the class constructor.
-
-
If __getinitargs__ is not defined, pickle.load
- will call the constructor (__init__) without arguments;
- i.e., the object must be default-constructible.
-
-
-
__getstate__
-
-
When an instance of a Boost.Python extension class is pickled, the
- pickler tests if the instance has a __getstate__ method. This
- method should return a Python object representing the state of the
- instance.
-
-
__setstate__
-
-
When an instance of a Boost.Python extension class is restored by
- the unpickler (pickle.load), it is first constructed using the
- result of __getinitargs__ as arguments (see above).
- Subsequently the unpickler tests if the new instance has a
- __setstate__ method. If so, this method is called with the
- result of __getstate__ (a Python object) as the argument.
-
The three special methods described above may be .def()'ed
- individually by the user. However, Boost.Python provides an easy to use
- high-level interface via the
- boost::python::pickle_suite class that also
- enforces consistency: __getstate__ and __setstate__
- must be defined as pairs. Use of this interface is demonstrated by the
- following examples.
-
-
-
Examples
There are three files in boost/libs/python/test
- that show how to provide pickle support.
-
-
-
The C++
- class in this example can be fully restored by passing the appropriate
- argument to the constructor. Therefore it is sufficient to define the
- pickle interface method __getinitargs__. This is done in the
- following way:
-
-
The C++
- class in this example contains member data that cannot be restored by any
- of the constructors. Therefore it is necessary to provide the
- __getstate__/__setstate__ pair of pickle interface
- methods:
-
-
For simplicity, the __dict__ is not included in the result of
- __getstate__. This is not generally recommended, but a valid
- approach if it is anticipated that the object's __dict__ will
- always be empty. Note that the safety guard described below will catch
- the cases where this assumption is violated.
This
- example is similar to pickle2.cpp. However, the object's
- __dict__ is included in the result of __getstate__.
- This requires a little more code but is unavoidable if the object's
- __dict__ is not always empty.
-
-
-
Pitfall and Safety Guard
The pickle protocol described above has
- an important pitfall that the end user of a Boost.Python extension module
- might not be aware of:
-
-
__getstate__ is defined and the instance's
- __dict__ is not empty.
-
-
The author of a Boost.Python extension class might provide a
- __getstate__ method without considering the possibilities
- that:
-
-
-
his class is used in Python as a base class. Most likely the
- __dict__ of instances of the derived class needs to be pickled
- in order to restore the instances correctly.
-
-
the user adds items to the instance's __dict__ directly.
- Again, the __dict__ of the instance then needs to be
- pickled.
-
-
-
To alert the user to this highly unobvious problem, a safety guard is
- provided. If __getstate__ is defined and the instance's
- __dict__ is not empty, Boost.Python tests if the class has an
- attribute __getstate_manages_dict__. An exception is raised if
- this attribute is not defined:
-
- RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
-
To resolve this problem, it should first be established that the
- __getstate__ and __setstate__ methods manage the
- instances's __dict__ correctly. Note that this can be done
- either at the C++ or the Python level. Finally, the safety guard should
- intentionally be overridden. E.g. in C++ (from pickle3.cpp):
-
- import your_bpl_module
- class your_class(your_bpl_module.your_class):
- __getstate_manages_dict__ = 1
- def __getstate__(self):
- # your code here
- def __setstate__(self, state):
- # your code here
-
-
-
-
Practical Advice
-
-
-
In Boost.Python extension modules with many extension classes,
- providing complete pickle support for all classes would be a
- significant overhead. In general complete pickle support should only be
- implemented for extension classes that will eventually be pickled.
-
-
Avoid using __getstate__ if the instance can also be
- reconstructed by way of __getinitargs__. This automatically
- avoids the pitfall described above.
-
-
If __getstate__ is required, include the instance's
- __dict__ in the Python object that is returned.
-
-
-
-
Light-weight alternative: pickle support implemented in Python
The
- pickle4.cpp example demonstrates an alternative technique for
- implementing pickle support. First we direct Boost.Python via the
- class_::enable_pickling() member function to define only the
- basic attributes required for pickling:
-
This enables the standard Python pickle interface as described in the
-Python documentation. By "injecting" a __getinitargs__ method into
-the definition of the wrapped class we make all instances pickleable:
-
- # import the wrapped world class
- from pickle4_ext import world
-
- # definition of __getinitargs__
- def world_getinitargs(self):
- return (self.get_country(),)
-
- # now inject __getinitargs__ (Python is a dynamic language!)
- world.__getinitargs__ = world_getinitargs
-
-
- Please see
- our regression
- logs for up-to-date information. Note that logs not marked
- otherwise reflect the CVS state, not the condition of the release.
-
-
- Earlier versions of Boost.Python have been successfully
- tested on the following platforms and compilers.
-
-
<boost/python/pointee.hpp> introduces a
- traits metafunction
- template pointee<T> that can be used to extract the "pointed-to" type from the type of a pointer or smart pointer.
-
-
Classes
-
-
Class Template pointee<class T>
-
-
pointee<T> is used by the class_<...>
- template to deduce the type being held when a pointer or smart
- pointer type is used as its HeldType argument.
-
-
-
-Given a 3rd-party smart pointer type
-smart_pointer<T>, one might partially specialize
-pointee<smart_pointer<T> > so that it can be
-used as the HeldType for a class wrapper:
-
-
-
-
-Monthly progress reports are required as part of Boost Consulting's
-contract with LLNL for Boost.Python development. These reports contain
-a useful record of the project history, including the rationale for
-design decisions and links to relevant discussions.
-
-
<boost/python/ptr.hpp> defines the
- ptr() function template, which allows users to
- specify how to convert C++ pointer values to python in the context
- of implementing overridable virtual functions, invoking Python
- callable objects, or explicitly converting C++ objects to
- Python. Normally, when passing pointers to Python callbacks, the
- pointee is copied to ensure that the Python object
- never holds a dangling reference. To specify that the new Python
- object should merely contain a copy of a pointer p,
- the user can pass ptr(p) instead of passing
- p directly. This interface is meant to mirror the use
- of boost::ref(),
- which can be similarly used to prevent copying of referents.
-
-
ptr(p) returns an instance of pointer_wrapper<>, which
- can be detected using the is_pointer_wrapper<>
- metafunction; unwrap_pointer<> is a
- metafunction which extracts the original pointer type from a
- pointer_wrapper<>. These classes can be thought
- of as implementation details.
-
-
Class template pointer_wrapper constructors and
- destructor
-
-explicit pointer_wrapper(Ptr x);
-
-
-
-
Requires:Ptr is a pointer type.
-
-
Effects: Stores x in a the pointer_wrapper<>.
-
Throws: nothing.
-
-
-
Class template pointer_wrapper observer
- functions
-
-operator Ptr() const;
-Ptr get() const;
-
-
-
-
Returns: a copy of the stored pointer.
-
Rationale:pointer_wrapper is intended
- to be a stand-in for the actual pointer type, but sometimes it's
- better to have an explicit way to retrieve the pointer.
-
-
-
Metafunctions
-
-
Class template is_pointer_wrapper
-
-
A unary metafunction whose value is true iff its
- argument is a pointer_wrapper<>.
-
-
Returns:T::type if T is a
- specialization of
-pointer_wrapper<>, T otherwise
-
-
-
-
Example(s)
-
-This example illustrates the use of ptr() to prevent an
-object from being copied:
-
-#include <boost/python/call.hpp>
-#include <boost/python/ptr.hpp>
-
-class expensive_to_copy
-{
- ...
-};
-
-void pass_as_arg(expensive_to_copy* x, PyObject* f)
-{
- // call the Python function f, passing a Python object built around
- // which refers to *x by-pointer.
- //
- // *** Note: ensuring that *x outlives the argument to f() is ***
- // *** up to the user! Failure to do so could result in a crash! ***
-
- boost::python::call<void>(f, ptr(x));
-}
-...
-
This is a convenience header which #includes all of the public
- interface headers that are part of the Boost.Python library
-
-# include <args.hpp>
-# include <args_fwd.hpp>
-# include <back_reference.hpp>
-# include <bases.hpp>
-# include <borrowed.hpp>
-# include <call.hpp>
-# include <call_method.hpp>
-# include <class.hpp>
-# include <copy_const_reference.hpp>
-# include <copy_non_const_reference.hpp>
-# include <data_members.hpp>
-# include <def.hpp>
-# include <default_call_policies.hpp>
-# include <dict.hpp>
-# include <enum.hpp>
-# include <errors.hpp>
-# include <exception_translator.hpp>
-# include <extract.hpp>
-# include <handle.hpp>
-# include <has_back_reference.hpp>
-# include <implicit.hpp>
-# include <init.hpp>
-# include <instance_holder.hpp>
-# include <iterator.hpp>
-# include <list.hpp>
-# include <long.hpp>
-# include <lvalue_from_pytype.hpp>
-# include <make_function.hpp>
-# include <manage_new_object.hpp>
-# include <module.hpp>
-# include <numeric.hpp>
-# include <object.hpp>
-# include <object_protocol.hpp>
-# include <object_protocol_core.hpp>
-# include <operators.hpp>
-# include <other.hpp>
-# include <overloads.hpp>
-# include <pointee.hpp>
-# include <ptr.hpp>
-# include <reference_existing_object.hpp>
-# include <return_internal_reference.hpp>
-# include <return_value_policy.hpp>
-# include <scope.hpp>
-# include <self.hpp>
-# include <slice_nil.hpp>
-# include <str.hpp>
-# include <to_python_converter.hpp>
-# include <to_python_indirect.hpp>
-# include <to_python_value.hpp>
-# include <tuple.hpp>
-# include <type_id.hpp>
-# include <with_custodian_and_ward.hpp>
-
To support Pythonic signatures the converters should supply a get_pytype function
- returning a pointer to the associated PyTypeObject. See for example
- ResultConverter or
- to_python_converter.
- The classes in this header file are meant to be used when implmenting get_pytype.
- There are also _direct versions of the templates of class T which
- should be used with undecorated type parameter, expected to be in the conversion registry when the module loads.
-
-
-
Classes
-
-
Class
- wrap_pytype
-
-
- This template generates a static get_pytype member returning the template parameter.
-
- This template should be used with template parameters which are (possibly decorated)
- types exported to python using class_.
- The generated a static get_pytype member
- returns the corresponding python type.
-
- This template generates a static get_pytype member which inspects the registered
- from_python converters for the type T and returns a matching python type.
-
-
- This example presumes that someone has implemented the standard noddy example
- module from the Python documentation, and placed the corresponding
- declarations in "noddy.h". Because
- noddy_NoddyObject is the ultimate trivial extension type,
- the example is a bit contrived: it wraps a function for which all
- information is contained in the type of its return value.
-
-
C++ module definition
-
-#include <boost/python/reference.hpp>
-#include <boost/python/module.hpp>
-#include "noddy.h"
-
-struct tag {};
-tag make_tag() { return tag(); }
-
-using namespace boost::python;
-
-struct tag_to_noddy
-#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
-: wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
-#endif
-{
- static PyObject* convert(tag const& x)
- {
- return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
- }
-};
-
-BOOST_PYTHON_MODULE(to_python_converter)
-{
- def("make_tag", make_tag);
- to_python_converter<tag, tag_to_noddy
-#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
- , true
-#endif
- >(); //"true" because tag_to_noddy has member get_pytype
-}
-
-
-
-
The following example registers to and from python converters using the templates
-expected_from_python_type and to_pyhton_target_type.
-
-
-#include <boost/python/module.hpp>
-#include <boost/python/def.hpp>
-#include <boost/python/extract.hpp>
-#include <boost/python/to_python_converter.hpp>
-#include <boost/python/class.hpp>
-
-using namespace boost::python;
-
-struct A
-{
-};
-
-struct B
-{
- A a;
- B(const A& a_):a(a_){}
-};
-
-// Converter from A to python int
-struct BToPython
-#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
- : converter::to_python_target_type<A> //inherits get_pytype
-#endif
-{
- static PyObject* convert(const B& b)
- {
- return incref(object(b.a).ptr());
- }
-};
-
-// Conversion from python int to A
-struct BFromPython
-{
- BFromPython()
- {
- boost::python::converter::registry::push_back
- ( &convertible
- , &construct
- , type_id< B >()
-#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
- , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
-#endif
- );
- }
-
- static void* convertible(PyObject* obj_ptr)
- {
- extract<const A&> ex(obj_ptr);
- if (!ex.check()) return 0;
- return obj_ptr;
- }
-
- static void construct(
- PyObject* obj_ptr,
- converter::rvalue_from_python_stage1_data* data)
- {
- void* storage = (
- (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
-
- extract<const A&> ex(obj_ptr);
- new (storage) B(ex());
- data->convertible = storage;
- }
-};
-
-
-B func(const B& b) { return b ; }
-
-BOOST_PYTHON_MODULE(pytype_function_ext)
-{
- to_python_converter< B , BToPython
-#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
- ,true
-#endif
- >(); //has get_pytype
- BFromPython();
-
- class_<A>("A") ;
-
- def("func", &func);
-
-}
-
-
-
->>> from pytype_function_ext import *
->>> print func.__doc__
-func( (A)arg1) -> A :
- C++ signature:
- struct B func(struct B)
-
raw_function(...)
- is used to convert a function taking a tuple and a dict into a Python callable object
- which accepts a variable number of arguments and arbitrary keyword
- arguments.
-
-
Returns: a callable object which requires at least min_args arguments. When called, the actual non-keyword arguments will be passed in a tuple as the first argument to f, and the keyword arguments will be passed in a dict as the second argument to f.
-
-
-
reference_existing_object is a model of ResultConverterGenerator
- which can be used to wrap C++ functions which return a reference or
- pointer to a C++ object. When the wrapped function is called, the value
- referenced by its return value is not copied. A new Python object is
- created which contains a pointer to the referent, and no attempt is made
- to ensure that the lifetime of the referent is at least as long as that
- of the corresponding Python object. Thus, it can be highly dangerous to use
- reference_existing_object without additional lifetime
- management from such models of CallPolicies as with_custodian_and_ward.
- This class is used in the implementation of return_internal_reference.
Returns:typedef to_python_indirect<T,V>
- type, where V is a class whose
- static execute function constructs an instance
- holder containing an unowned
- U* pointing to the referent of the wrapped function's
- return value.
-
-
-
Example
-
-
In C++:
-
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/reference_existing_object.hpp>
-#include <boost/python/return_value_policy.hpp>
-#include <utility>
-
-// classes to wrap
-struct Singleton
-{
- Singleton() : x(0) {}
-
- int exchange(int n) // set x and return the old value
- {
- std::swap(n, x);
- return n;
- }
-
- int x;
-};
-
-Singleton& get_it()
-{
- static Singleton just_one;
- return just_one;
-}
-
-// Wrapper code
-using namespace boost::python;
-BOOST_PYTHON_MODULE(singleton)
-{
- def("get_it", get_it,
- return_value_policy<reference_existing_object>());
-
- class_<Singleton>("Singleton")
- .def("exchange", &Singleton::exchange)
- ;
-}
-
- In Python:
-
->>> import singleton
->>> s1 = singleton.get_it()
->>> s2 = singleton.get_it()
->>> id(s1) == id(s2) # s1 and s2 are not the same object
-0
->>> s1.exchange(42) # but they reference the same C++ Singleton
-0
->>> s2.exchange(99)
-42
-
- <boost/python/register_ptr_to_python.hpp>
- supplies register_ptr_to_python, a function template
- which registers a conversion for smart pointers to Python. The
- resulting Python object holds a copy of the converted smart pointer,
- but behaves as though it were a wrapped copy of the pointee. If
- the pointee type has virtual functions and the class representing
- its dynamic (most-derived) type has been wrapped, the Python object
- will be an instance of the wrapper for the most-derived type. More than
- one smart pointer type for a pointee's class can be registered.
-
-
- Note that in order to convert a Python X object to a
- smart_ptr<X>& (non-const reference), the embedded C++
- object must be held by smart_ptr<X>, and that when wrapped
- objects are created by calling the constructor from Python, how they are held
- is determined by the HeldType parameter to
- class_<...> instances.
-
->>> from register_ptr import *
->>> a = A()
->>> Ok(a) # ok, passed as shared_ptr<A>
-0
->>> Fail(a) # passed as shared_ptr<A>&, and was created in Python!
-Traceback (most recent call last):
- File "<stdin>", line 1, in ?
-TypeError: bad argument type for built-in operation
->>>
->>> na = New() # now "na" is actually a shared_ptr<A>
->>> Ok(a)
-0
->>> Fail(a)
-0
->>>
-
-
-There will be an error when trying to convert shared_ptr<A> to
-shared_ptr<A_Wrapper>:
-
-
->>> a = New()
-Traceback (most recent call last):
-File "<stdin>", line 1, in ?
-TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
->>>
-
- return_arg and return_self instantiations are
- models of CallPolicies which return the
- specified argument parameter (usually *this) of a wrapped
- (member) function.
-
-
Classes
-
-
Class template
- return_arg
-
-
-
- return_arg template parameters
-
-
-
-
Parameter
-
-
Requirements
-
-
Description
-
-
Default
-
-
-
-
arg_pos
-
-
A positive compile-time constant of type
- std::size_t.
Used for policy composition. Any result_converter it
- supplies will be overridden by return_arg, but its
- precall and postcall policies are composed
- as described here CallPolicies.
return_by_value is a model of ResultConverterGenerator
- which can be used to wrap C++ functions returning any reference or value
- type such that the return value is copied into a new Python object.
- return_internal_reference instantiations are models of CallPolicies which allow pointers and
- references to objects held internally by a free or member function
- argument or from the target of a member function to be returned safely
- without making a copy of the referent. The default for its first template
- argument handles the common case where the containing object is the
- target (*this) of a wrapped member function.
-
-
Classes
-
-
Class template
- return_internal_reference
-
-
-
- return_internal_reference template parameters
-
-
-
-
Parameter
-
-
Requirements
-
-
Description
-
-
Default
-
-
-
-
owner_arg
-
-
A positive compile-time constant of type
- std::size_t.
-
-
The index of the parameter which contains the object to which the
- reference or pointer is being returned. If used to wrap a member
- function, parameter 1 is the target object (*this). Note
- that if the target Python object type doesn't support weak
- references, a Python TypeError exception will be raised
- when the function being wrapped is called.
Used for policy composition. Any result_converter it
- supplies will be overridden by
- return_internal_reference, but its precall
- and postcall policies are composed as described here CallPolicies.
return_opaque_pointer is a model of
-
- ResultConverterGenerator
- which can be used to wrap C++ functions returning pointers to
- undefined types such that the return value is copied into a
- new Python object.
-
In addition to specifying the return_opaque_pointer
- policy the
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID macro must be
- used to define specializations for the
- type_id function
- on the type pointed to by returned pointer.
Defines facilities for querying and controlling the Python scope
- (namespace) which will contain new wrapped classes and functions.
-
-
Classes
-
-
Class scope
-
-
The scope class has an associated global Python
- object which controls the Python namespace in which new extension
- classes and wrapped functions will be defined as
- attributes. Default-constructing a new scope object
- binds it to the associated global Python object. Constructing a
- scope object with an argument changes the associated
- global Python object to the one held by the argument, until the
- lifetime of the scope object ends, at which time the
- associated global Python object reverts to what it was before the
- scope object was constructed.
- Stores a reference to the current associated scope object, and sets the
- associated scope object to the one referred to by x.ptr().
- The object base class is initialized with x.
-
-scope();
-
- Stores a reference to the current associated scope object. The
- object base class is initialized with the current associated
- scope object. Outside any module initialization function, the current
- associated Python object is None.
-
-~scope()
-
- Sets the current associated Python object to the stored object.
-
-
Example
- The following example shows how scope setting can be used to define
- nested classes.
-
-
C++ Module definition:
-
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/scope.hpp>
-using namespace boost::python;
-
-struct X
-{
- void f() {}
-
- struct Y { int g() { return 42; } };
-};
-
-BOOST_PYTHON_MODULE(nested)
-{
- // add some constants to the current (module) scope
- scope().attr("yes") = 1;
- scope().attr("no") = 0;
-
- // Change the current scope
- scope outer
- = class_<X>("X")
- .def("f", &X::f)
- ;
-
- // Define a class Y in the current scope, X
- class_<X::Y>("Y")
- .def("g", &X::Y::g)
- ;
-}
-
Exposes the extended slicing protocol by wrapping the built-in slice
-type. The semantics of the constructors and member functions defined
-below can be fully understood by reading the TypeWrapper concept
-definition. Since slice is publicly derived from object, the public object
-interface applies to slice instances as well.
-
-
Class slice synopsis
-
-namespace boost { namespace python
-{
- class slice : public object
- {
- public:
- slice(); // create an empty slice, equivalent to [::]
-
- template <typename Int1, typename Int2>
- slice(Int1 start, Int2 stop);
-
- template <typename Int1, typename Int2, typename Int3>
- slice(Int1 start, Int2 stop, Int3 step);
-
- // Access the parameters this slice was created with.
- object start();
- object stop();
- object step();
-
- // The return type of slice::get_indices()
- template <typename RandomAccessIterator>
- struct range
- {
- RandomAccessIterator start;
- RandomAccessIterator stop;
- int step;
- };
-
- template <typename RandomAccessIterator>
- range<RandomAccessIterator>
- get_indices(
- RandomAccessIterator const& begin,
- RandomAccessIterator const& end);
- };
-}}
-
-
Class slice
-constructors
-
-
slice();
-
-
Effects: constructs a slice with default stop, start, and
-step values. Equivalent to the slice object created as part of the Python
-expression base[::].
Requires:start, stop, and step
- are of type slice_nil
- or convertible to type object.
-
Effects: constructs a new slice with default step value
-and the provided start and stop values. Equivalent to the slice
-object
-created by the built-in Python function slice(start,stop),
-or as part of the Python expression base[start:stop].
-
Throws:error_already_set and sets a Python TypeError
-exception if no conversion is possible from the arguments to type object.
Requires:start, stop, and step are slice_nil or convertible to type object.
-
Effects: constructs a new slice with start stop and step
-values. Equivalent to the slice object created
-by the built-in Python function slice(start,stop,step),
-or as part of the Python expression base[start:stop:step].
-
Throws:error_already_set and sets a Python TypeError
-exception if no conversion is possible from the arguments to type
-object.
Returns:the parameter that
-the slice was created with. If the parameter was omitted or
-slice_nil was used when the slice was created, than that parameter will
-be a reference to PyNone and compare equal to a default-constructed
-object. In principal, any object may be used when creating a
-slice object, but in practice they are usually integers.
Arguments: A pair of STL-conforming Random Access
-Iterators that form a half-open range.
-
Effects: Create a RandomAccessIterator pair that defines a
-fully-closed range within the [begin,end) range of its arguments.
-This function translates this slice's indices while accounting for the
-effects of any PyNone or negative indices, and non-singular step sizes.
-
Returns: a slice::range
-that has been initialized with a non-zero value of step and a pair of
-RandomAccessIterators that point within the range of this functions
-arguments and define a closed interval.
-
Throws:Raises a Python TypeError exception if any of this slice's arguments
-are neither references to PyNone nor convertible to int. Throws
-std::invalid_argument if the resulting range would be empty. You
-should always wrap calls to slice::get_indices()
-within try { ...; } catch (std::invalid_argument) {} to
-handle this case and take appropriate action.
-
Rationale: closed-interval: If
-an open interval were used, then for step
-size other than 1, the required state for the end iterator would point
-beyond the one-past-the-end position or before the beginning of the
-specified range.
-exceptions on empty slice: It is impossible to define a closed interval
-over an empty range, so some other form of error checking would have to
-be used to prevent undefined behavior. In the case where the
-exception is not caught, it will simply be translated to Python by the
-default exception handling mechanisms.
-
-
Examples
-
-using namespace boost::python;
-
-// Perform an extended slice of a Python list.
-// Warning: extended slicing was not supported for built-in types prior
-// to Python 2.3
-list odd_elements(list l)
-{
- return l[slice(_,_,2)];
-}
-
-// Perform a multidimensional extended slice of a Numeric.array
-numeric::array even_columns(numeric::array arr)
-{
- // select every other column, starting with the second, of a 2-D array.
- // Equivalent to "return arr[:, 1::2]" in Python.
- return arr[make_tuple( slice(), slice(1,_,2))];
-}
-
-// Perform a summation over a slice of a std::vector.
-double partial_sum(std::vector<double> const& Foo, const slice index)
-{
- slice::range<std::vector<double>::const_iterator> bounds;
- try {
- bounds = index.get_indices<>(Foo.begin(), Foo.end());
- }
- catch (std::invalid_argument) {
- return 0.0;
- }
- double sum = 0.0;
- while (bounds.start != bounds.stop) {
- sum += *bounds.start;
- std::advance( bounds.start, bounds.step);
- }
- sum += *bounds.start;
- return sum;
-}
-
Python 2.5 introduces a new Py_ssize_t typedef and
- two related macros (PEP 353). The
- <boost/python/ssize_t.hpp> header imports these
- definitions into the boost::python namespace as
- ssize_t, ssize_t_max, and ssize_t_min.
- Appropriate definitions are provided for backward compatibility
- with previous Python versions.
-
-
Typedefs
Imports
- Py_ssize_t into the boost::python namespace if
- available, or provides an appropriate typedef for backward
- compatibility:
-
Imports
- PY_SSIZE_T_MAX and PY_SSIZE_T_MIN as constants
- into the boost::python namespace if available, or
- provides appropriate constants for backward compatibility:
-
Instances of stl_input_iterator<T> hold a Python
- iterator and adapt it for use with STL algorithms.
- stl_input_iterator<T> satisfies the requirements for
- an Input Iterator.
-
-
-
-
-
Template Parameter
-
-
Requirements
-
-
Semantics
-
-
Default
-
-
-
-
ValueType
-
-
ValueType must be CopyConstructible.
-
-
Dereferencing an instance of stl_input_iterator<ValueType>
- will return an rvalue of type ValueType.
- Class Template stl_input_iterator
- constructors
-
-
-
-stl_input_iterator()
-
-
-
-
Effects:
- Creates a past-the-end input iterator, useful for signifying the end of a sequence.
-
-
Postconditions:this is past-the-end.
-
Throws: Nothing.
-
-
-
-stl_input_iterator(object const& ob)
-
-
-
-
Effects:
- Calls ob.attr("__iter__")() and stores the resulting Python iterator
- object in this->it. Then, calls this->it.attr("next")() and
- stores the result in this->ob. If the sequence is exhausted, sets
- this->ob to object().
-
-
-
Postconditions:this is a dereferenceable or past-the-end.
-
-
-
- Class Template stl_input_iterator
- modifiers
-
-
-
-stl_input_iterator& operator++()
-
-
-
-
Effects:
- Calls this->it.attr("next")() and stores the result in
- this->ob. If the sequence is exhausted, sets this->ob
- to object().
-
-
-
Postconditions:this is a dereferenceable or past-the-end.
Exposes the string
- methods of Python's built-in str type. The
- semantics of the constructors and member functions defined below,
- except for the two-argument constructors which construct str
- objects from a range of characters, can be fully understood by
- reading the TypeWrapper concept
- definition. Since str is publicly derived from
- object, the
- public object interface applies to str instances as
- well.
- to_python_converter registers a conversion from objects of a
- given C++ type into a Python object.
-
-
Classes
-
-
Class template
- to_python_converter
- to_python_converter adds a wrapper around a static member
- function of its second template parameter, handling low-level details
- such as insertion into the converter registry.
-
-
-
- to_python_converter template parameters
- In the table below, x denotes an object of type
- T
-
-
-
-
Parameter
-
-
Requirements
-
-
Description
-
-
-
-
T
-
-
-
-
-
The C++ type of the source object in the conversion
-
-
-
-
Conversion
-
-
- PyObject* p = Conversion::convert(x),
- if p == 0, PyErr_Occurred() != 0.
-
-
A class type whose static member function convert
- does the real work of the conversion.
-
-
-
bool has_get_pytype = false
-
-
- PyTypeObject const * p = Conversion::get_pytype() .
-
-
Optional member - if Conversion has get_pytype member supply
- true for this parameters.
- If present get_pytype is used to document the return type
- of functions using this conversion. The get_pytype may be implemented
- using the classes and functions
- from pytype_function.hpp
- NOTE : For backward compatibility this parameter may be passed after
- checking if BOOST_PYTHON_SUPPORTS_PY_SIGNATURES is defined (see
- here).
-
Effects: Registers a to_python converter which uses
- Conversion::convert() to do its work.
-
-
-
Example
- This example presumes that someone has implemented the standard noddy example
- module from the Python documentation, and placed the corresponding
- declarations in "noddy.h". Because
- noddy_NoddyObject is the ultimate trivial extension type,
- the example is a bit contrived: it wraps a function for which all
- information is contained in the type of its return value.
-
-
-
- <boost/python/to_python_indirect.hpp> supplies
- a way to construct new Python objects that hold wrapped C++ class
- instances via a pointer or smart pointer.
-
-
Classes
-
-
Class template to_python_indirect
-
Class template to_python_indirect converts objects
-of its first argument type to python as extension class instances, using the ownership policy provided by its 2nd argument.
-
-
-
-
-
-
- to_python_indirect Requirements
-
- In the table below, x denotes an object of
- type T, h denotes an
- object of type
- boost::python::objects::instance_holder*, and
- p denotes an object of type
- U*.
-
-
-
-
Parameter
-
-
Requirements
-
-
Description
-
-
-
T
-
-
Either Ucv&
- (where cv is any optional cv-qualification) or a Dereferenceable type such that
- *x is convertible to U const&, where
- U is a class type.
-
-
A type deferencing a C++ class exposed to Python using
- class template class_.
-
-
-
MakeHolder
-
-
h = MakeHolder::execute(p);
-
-
A class whose static execute() creates an
- instance_holder.
-
-
-
- Instantiations of to_python_indirect are models of ResultConverter.
-
-
-
Requires:x refers to an object (if it
- is a pointer type, it is non-null). convertible() ==
- true.
-
-
Effects: Creates an appropriately-typed Boost.Python
- extension class instance, uses MakeHolder to create
- an instance_holder from x, installs
- the instance_holder in the new extension class
- instance, and returns a pointer to it.
-
-
-
-
-
Class template to_python_indirect statics
-
-bool convertible();
-
-
-
Effects: Returns true iff any module has
- registered a Python type corresponding to U.
-
-
Example
-
-This example replicates the functionality of reference_existing_object,
-but without some of the compile-time error checking.
-
-
-
Exposes the interface of Python's built-in tuple type.
- The semantics of the constructors and member functions defined below can
- be fully understood by reading the TypeWrapper concept
- definition. Since tuple is publicly derived from object, the public object
- interface applies to tuple instances as well.
<boost/python/type_id.hpp> provides types and
- functions for runtime type identification like those of of
- <typeinfo>. It exists mostly to work around certain
- compiler bugs and platform-dependent interactions with shared
- libraries.
-
-
Classes
-
-
Class type_info
-
-
type_info instances identify a type. As
- std::type_info is specified to (but unlike its
- implementation in some compilers), boost::python::type_info
- never represents top-level references or cv-qualification (see section
- 5.2.8 in the C++ standard). Unlike std::type_info,
- boost::python::type_info instances are copyable, and
- comparisons always work reliably across shared library boundaries.
Effects: constructs a type_info object which
- identifies the same type as its argument.
-
-
Rationale: Since it is occasionally necessary to make an
- array of type_info objects a benign default argument is
- supplied. Note: this constructor does
- not correct for non-conformance of compiler
- typeid() implementations. See type_id, below.
Effects: Writes a description of the type described by to
- x into s.
-
-
Rationale: Not every C++ implementation provides a truly
- human-readable type_info::name() string, but for some we
- may be able to decode the string and produce a reasonable
- representation.
Note: On some non-conforming C++ implementations, the code
- is not actually as simple as described above; the semantics are
- adjusted to work as-if the C++ implementation were
- conforming.
-
-
-
Example
- The following example, though silly, illustrates how the
- type_id facility might be used
-
-#include <boost/python/type_id.hpp>
-
-// Returns true iff the user passes an int argument
-template <class T>
-bool is_int(T x)
-{
- using boost::python::type_id;
- return type_id<T>() == type_id<int>();
-}
-