2
0
mirror of https://github.com/boostorg/python.git synced 2026-02-02 09:02:15 +00:00

Remove unused content from doc branch.

This commit is contained in:
Stefan Seefeld
2016-08-06 01:09:52 -04:00
parent 56e41f3bf2
commit 986173e731
625 changed files with 0 additions and 60128 deletions

View File

@@ -1,151 +0,0 @@
# Copyright David Abrahams 2001-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)
import os ;
import indirect ;
import modules ;
import feature ;
import python ;
if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
{
# Attempt default configuration of python
import toolset : using ;
using python ;
}
if [ python.configured ] || ( --without-python in [ modules.peek : ARGV ] )
{
alias config-warning ;
}
else
{
message config-warning
: "warning: No python installation configured and autoconfiguration"
: "note: failed. See http://www.boost.org/libs/python/doc/building.html"
: "note: for configuration instructions or pass --without-python to"
: "note: suppress this message and silently skip all Boost.Python targets"
;
}
rule find-py3-version
{
local versions = [ feature.values python ] ;
local py3ver ;
for local v in $(versions)
{
if $(v) >= 3.0
{
py3ver = $(v) ;
}
}
return $(py3ver) ;
}
py3-version = [ find-py3-version ] ;
project boost/python
: source-location ../src
: requirements
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
if $(name) = boost_python && $(PYTHON_ID)
{
result = $(result)-$(PYTHON_ID) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
rule lib_boost_python ( is-py3 ? )
{
lib [ cond $(is-py3) : boost_python3 : boost_python ]
: # sources
numeric.cpp
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
converter/from_python.cpp
converter/registry.cpp
converter/type_id.cpp
object/enum.cpp
object/class.cpp
object/function.cpp
object/inheritance.cpp
object/life_support.cpp
object/pickle_support.cpp
errors.cpp
module.cpp
converter/builtin_converters.cpp
converter/arg_to_python_base.cpp
object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
: # requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
# On Windows, all code using Python has to link to the Python
# import library.
#
# On *nix we never link libboost_python to libpython. When
# extending Python, all Python symbols are provided by the
# Python interpreter executable. When embedding Python, the
# client executable is expected to explicitly link to
# /python//python (the target representing libpython) itself.
#
# python_for_extensions is a target defined by Boost.Build to
# provide the Python include paths, and on Windows, the Python
# import library, as usage requirements.
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
# we prevent building when there is no python available
# as it's not possible anyway, and to cause dependents to
# fail to build
[ unless [ python.configured ] : <build>no ]
<dependency>config-warning
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
[ cond $(is-py3) : <python>$(py3-version) ]
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
}
lib_boost_python ;
boost-install boost_python ;
if $(py3-version)
{
lib_boost_python yes ;
boost-install boost_python3 ;
}

Binary file not shown.

View File

@@ -1,47 +0,0 @@
# Copyright (c) 2006 Joel de Guzman
# Copyright (c) 2015 Stefan Seefeld
#
# 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)
path-constant here : . ;
path-constant images : html/images ;
project python/doc
: requirements <format>html:<xsl:param>boost.defaults=none
<format>html:<xsl:param>toc.max.depth=3
<format>html:<xsl:param>toc.section.depth=2
<format>html:<xsl:param>chunk.section.depth=1
;
import boostbook ;
import quickbook ;
import docutils ;
boostbook python : python.qbk
: <format>html:<name>$(here)/html
<format>html:<xsl:param>generate.toc="library nop; chapter toc; section toc;"
<format>html:<xsl:param>html.stylesheet=boostbook.css
<format>html:<xsl:param>boost.image.src=images/boost.png
<format>html:<xsl:param>boost.graphics.root=images/
;
boostbook tutorial : tutorial.qbk
: <format>html:<name>$(here)/html/tutorial
<format>html:<xsl:param>html.stylesheet=../boostbook.css
<format>html:<xsl:param>boost.image.src=../images/boost.png
<format>html:<xsl:param>boost.graphics.root=../images/
;
boostbook reference : reference.qbk
: <format>html:<name>$(here)/html/reference
<format>html:<xsl:param>html.stylesheet=../boostbook.css
<format>html:<xsl:param>boost.image.src=../images/boost.png
<format>html:<xsl:param>boost.graphics.root=../images/
;
html article : article.rst
: <location>html
<docutils-html>"--link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css"
;

View File

@@ -1,947 +0,0 @@
+++++++++++++++++++++++++++++++++++++++++++
Building Hybrid Systems with Boost.Python
+++++++++++++++++++++++++++++++++++++++++++
:Author: David Abrahams
:Contact: dave@boost-consulting.com
:organization: `Boost Consulting`_
:date: 2003-05-14
:Author: Ralf W. Grosse-Kunstleve
:copyright: Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved
.. contents:: Table of Contents
.. _`Boost Consulting`: http://www.boost-consulting.com
==========
Abstract
==========
Boost.Python is an open source C++ library which provides a concise
IDL-like interface for binding C++ classes and functions to
Python. Leveraging the full power of C++ compile-time introspection
and of recently developed metaprogramming techniques, this is achieved
entirely in pure C++, without introducing a new syntax.
Boost.Python's rich set of features and high-level interface make it
possible to engineer packages from the ground up as hybrid systems,
giving programmers easy and coherent access to both the efficient
compile-time polymorphism of C++ and the extremely convenient run-time
polymorphism of Python.
==============
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
compile-time meta-language, while in Python, practically everything
happens at runtime.
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.
Given Python's rich 'C' interoperability API, it should in principle
be possible to expose C++ type and function interfaces to Python with
an analogous interface to their C++ counterparts. However, the
facilities provided by Python alone for integration with C++ are
relatively meager. Compared to C++ and Python, 'C' has only very
rudimentary abstraction facilities, and support for exception-handling
is completely missing. 'C' extension module writers are required to
manually manage Python reference counts, which is both annoyingly
tedious and extremely error-prone. Traditional extension modules also
tend to contain a great deal of boilerplate code repetition which
makes them difficult to maintain, especially when wrapping an evolving
API.
These limitations 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 SIP_,
which was specifically designed for interfacing Python with the Qt_
graphical user interface library. Both SWIG and SIP introduce their
own specialized languages for customizing inter-language bindings.
This has certain 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.
The features and goals of Boost.Python_ overlap significantly with
many of these other systems. That said, Boost.Python attempts to
maximize convenience and flexibility without introducing a separate
wrapping language. Instead, it presents the user with a high-level
C++ interface for wrapping C++ classes and functions, managing much of
the complexity behind-the-scenes with static metaprogramming.
Boost.Python also goes beyond the scope of earlier systems by
providing:
* Support for C++ virtual functions that can be overridden in Python.
* Comprehensive lifetime management facilities for low-level C++
pointers and references.
* Support for organizing extensions as Python packages,
with a central registry for inter-language type conversions.
* A safe and convenient mechanism for tying into Python's powerful
serialization engine (pickle).
* Coherence with the rules for handling C++ lvalues and rvalues that
can only come from a deep understanding of both the Python and C++
type systems.
The key insight that sparked the development of Boost.Python is that
much of the boilerplate code in traditional extension modules could be
eliminated using C++ compile-time introspection. Each argument of a
wrapped C++ function must be extracted from a Python object using a
procedure that depends on the argument type. Similarly the function's
return type determines how the return value will be converted from C++
to Python. Of course argument and return types are part of each
function's type, and this is exactly the source from which
Boost.Python deduces most of the information required.
This approach leads to *user guided wrapping*: as much information is
extracted directly from the source code to be wrapped as is possible
within the framework of pure C++, and some additional information is
supplied explicitly by the user. Mostly the guidance is mechanical
and little real intervention is required. Because the interface
specification is written in the same full-featured language as the
code being exposed, the user has unprecedented power available when
she does need to take control.
.. _Python: http://www.python.org/
.. _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: http://www.boost.org/libs/python/doc
===========================
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 <boost/python.hpp>
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,
it's worth noting a few things that it doesn't handle 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. Boost.Python'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
neccessary to avoid confusion, details of library implementation are
omitted.
------------------
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.hpp>
BOOST_PYTHON_MODULE(hello)
{
class_<World>("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 Boost.Python. To break it down::
class_<World>("World")
constructs an unnamed object of type ``class_<World>`` 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 Boost.Python type conversion registry. We
might have also written::
class_<World> 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_<World> 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 article
will 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>("World", init<std::string>())
...
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>("World", init<std::string>())
.def(init<double, double>())
...
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>("World", init<std::string>())
.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. Boost.Python 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.
Boost.Python bridges this idiomatic gap by making Python ``property``
creation directly available to users. If ``msg`` were private, we
could still expose it as attribute in Python as follows::
class_<World>("World", init<std::string>())
.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)
Operator Overloading
====================
The ability to write arithmetic operators for user-defined types has
been a major factor in the success of both languages for numerical
computation, and the success of packages like NumPy_ attests to the
power of exposing operators in extension modules. Boost.Python
provides a concise mechanism for wrapping operator overloads. The
example below shows a fragment from a wrapper for the Boost rational
number library::
class_<rational<int> >("rational_int")
.def(init<int, int>()) // constructor, e.g. rational_int(3,4)
.def("numerator", &rational<int>::numerator)
.def("denominator", &rational<int>::denominator)
.def(-self) // __neg__ (unary minus)
.def(self + self) // __add__ (homogeneous)
.def(self * self) // __mul__
.def(self + int()) // __add__ (heterogenous)
.def(int() + self) // __radd__
...
The magic is performed using a simplified application of "expression
templates" [VELD1995]_, a technique originally developed 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 evaluating each operation "greedily".
Boost.Python uses the same technique to build an appropriate Python
method object based on expressions involving ``self``.
.. _NumPy: http://www.pfdubois.com/numpy/
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, bases<Base1,Base2> >("Derived")
...
This has two effects:
1. When the ``class_<...>`` is created, Python type objects
corresponding to ``Base1`` and ``Base2`` are looked up in
Boost.Python's registry, and are used as bases for the new Python
``Derived`` type object, 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
neccessary 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(SomeBoostPythonClass):
... def __init__(self):
... pass
...
>>> D().some_boost_python_method()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: bad argument type for built-in operation
This happened because Boost.Python couldn't find instance data of type
``SomeBoostPythonClass`` 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
``SomeBoostPythonClass.__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<int>(self, "f", x); }
};
...
def("calls_f", calls_f);
class_<Base, BaseWrap>("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``.
Deeper Reflection on the Horizon?
=================================
Admittedly, this formula is tedious to repeat, especially on a project
with many polymorphic classes. That it is neccessary reflects some
limitations in C++'s compile-time introspection capabilities: there's
no way to enumerate the members of a class and find out which are
virtual functions. At least one very promising project has been
started to write a front-end which can generate these dispatchers (and
other wrapping code) automatically from C++ headers.
Pyste_ is being developed by Bruno da Silva de Oliveira. It builds on
GCC_XML_, which generates an XML version of GCC's internal program
representation. Since GCC is a highly-conformant C++ compiler, this
ensures correct handling of the most-sophisticated template code and
full access to the underlying type system. In keeping with the
Boost.Python philosophy, a Pyste interface description is neither
intrusive on the code being wrapped, nor expressed in some unfamiliar
language: instead it is a 100% pure Python script. If Pyste is
successful it will mark a move away from wrapping everything directly
in C++ for many of our users. It will also allow us the choice to
shift some of the metaprogram code from C++ to Python. We expect that
soon, not only our users but the Boost.Python developers themselves
will be "thinking hybrid" about their own code.
.. _`GCC_XML`: http://www.gccxml.org/HTML/Index.html
.. _`Pyste`: http://www.boost.org/libs/python/pyste
---------------
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 just 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 <string>
struct World
{
World(std::string a_msg) : msg(a_msg) {}
std::string greet() const { return msg; }
std::string msg;
};
#include <boost/python.hpp>
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>("World", init<std::string>())
.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. Like a __getinitargs__
function in Python, the pickle_suite's getinitargs() is responsible for
creating the argument tuple that will be use to reconstruct the pickled
object. The other elements of the Python pickling protocol,
__getstate__ and __setstate__ can be optionally provided via C++
getstate and setstate functions. C++'s static type system allows the
library to ensure at compile-time that nonsensical combinations of
functions (e.g. getstate without setstate) are not used.
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 'C' language extension module authors will be familiar
with the ubiquitous ``PyObject*``, manual reference-counting, and the
need to remember which API calls return "new" (owned) references or
"borrowed" (raw) references. These constraints are not just
cumbersome but also a major source of errors, especially in the
presence of exceptions.
Boost.Python provides a class ``object`` which automates reference
counting and provides conversion to Python from C++ objects of
arbitrary type. This significantly reduces the learning effort for
prospective extension module writers.
Creating an ``object`` from any other type is extremely simple::
object s("hello, world"); // s manages a Python string
``object`` has templated interactions with all other types, with
automatic to-python conversions. It happens so naturally that it's
easily overlooked::
object ten_Os = 10 * s[4]; // -> "oooooooooo"
In the example above, ``4`` and ``10`` are converted to Python objects
before the indexing and multiplication operations are invoked.
The ``extract<T>`` class template can be used to convert Python objects
to C++ types::
double x = extract<double>(o);
If a conversion in either direction cannot be performed, an
appropriate exception is thrown at runtime.
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++. Of course we can wrap C++ functions which accept or return
``object`` instances.
=================
Thinking hybrid
=================
Because of the practical and mental difficulties of combining
programming languages, it is common to settle a single language at the
outset of any development effort. For many applications, performance
considerations dictate the use of a compiled language for the core
algorithms. Unfortunately, due to the complexity of the static type
system, the price we pay for runtime performance is often a
significant increase in development time. Experience shows that
writing maintainable C++ code usually takes longer and requires *far*
more hard-earned working experience than developing comparable Python
code. Even when developers are comfortable working exclusively in
compiled languages, they often augment their systems by some type of
ad hoc scripting layer for the benefit of their users without ever
availing themselves of the same advantages.
Boost.Python enables us to *think hybrid*. Python can be used for
rapidly prototyping a new application; its ease of use and the large
pool of standard libraries give us a head start on the way to a
working system. If necessary, the working code can be used to
discover rate-limiting hotspots. 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 C++. 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. 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.
.. 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
ratio to level out near 70% Python. Being able to solve new problems
mostly in Python rather than a more difficult statically typed
language is the return on our investment in Boost.Python. The ability
to access all of our code from Python allows a broader group of
developers to use it in the rapid development of new applications.
=====================
Development history
=====================
The first version of Boost.Python was developed in 2000 by Dave
Abrahams at Dragon Systems, where he was privileged to have Tim Peters
as a guide to "The Zen of Python". One of Dave's jobs was to develop
a Python-based natural language processing system. Since it was
eventually going to be targeting embedded hardware, it was always
assumed that the compute-intensive core would be rewritten in C++ to
optimize speed and memory footprint [#proto]_. The project also wanted to
test all of its C++ code using Python test scripts [#test]_. The only
tool we knew of for binding C++ and Python was SWIG_, and at the time
its handling of C++ was weak. It would be false to claim any deep
insight into the possible advantages of Boost.Python's approach at
this point. Dave's interest and expertise in fancy C++ template
tricks had just reached the point where he could do some real damage,
and Boost.Python emerged as it did because it filled a need and
because it seemed like a cool thing to try.
This early version was aimed at many of the same basic goals we've
described in this paper, differing most-noticeably by having a
slightly more cumbersome syntax and by lack of special support for
operator overloading, pickling, and component-based development.
These last three features were quickly added by Ullrich Koethe and
Ralf Grosse-Kunstleve [#feature]_, and other enthusiastic contributors arrived
on the scene to contribute enhancements like support for nested
modules and static member functions.
By early 2001 development had stabilized and few new features were
being added, however a disturbing new fact came to light: Ralf had
begun testing Boost.Python on pre-release versions of a compiler using
the EDG_ front-end, and the mechanism at the core of Boost.Python
responsible for handling conversions between Python and C++ types was
failing to compile. As it turned out, we had been exploiting a very
common bug in the implementation of all the C++ compilers we had
tested. We knew that as C++ compilers rapidly became more
standards-compliant, the library would begin failing on more
platforms. Unfortunately, because the mechanism was so central to the
functioning of the library, fixing the problem looked very difficult.
Fortunately, later that year Lawrence Berkeley and later Lawrence
Livermore National labs contracted with `Boost Consulting`_ for support
and development of Boost.Python, and there was a new opportunity to
address fundamental issues and ensure a future for the library. A
redesign effort began with the low level type conversion architecture,
building in standards-compliance and support for component-based
development (in contrast to version 1 where conversions had to be
explicitly imported and exported across module boundaries). A new
analysis of the relationship between the Python and C++ objects was
done, resulting in more intuitive handling for C++ lvalues and
rvalues.
The emergence of a powerful new type system in Python 2.2 made the
choice of whether to maintain compatibility with Python 1.5.2 easy:
the opportunity to throw away a great deal of elaborate code for
emulating classic Python classes alone was too good to pass up. In
addition, Python iterators and descriptors provided crucial and
elegant tools for representing similar C++ constructs. The
development of the generalized ``object`` interface allowed us to
further shield C++ programmers from the dangers and syntactic burdens
of the Python 'C' API. A great number of other features including C++
exception translation, improved support for overloaded functions, and
most significantly, CallPolicies for handling pointers and
references, were added during this period.
In October 2002, version 2 of Boost.Python was released. Development
since then has concentrated on improved support for C++ runtime
polymorphism and smart pointers. Peter Dimov's ingenious
``boost::shared_ptr`` design in particular has allowed us to give the
hybrid developer a consistent interface for moving objects back and
forth across the language barrier without loss of information. At
first, we were concerned that the sophistication and complexity of the
Boost.Python v2 implementation might discourage contributors, but the
emergence of Pyste_ and several other significant feature
contributions have laid those fears to rest. Daily questions on the
Python C++-sig and a backlog of desired improvements show that the
library is getting used. To us, the future looks bright.
.. _`EDG`: http://www.edg.com
=============
Conclusions
=============
Boost.Python achieves seamless interoperability between two rich and
complimentary language environments. Because it leverages template
metaprogramming to introspect about types and functions, the user
never has to learn a third syntax: the interface definitions are
written in concise and maintainable C++. Also, the wrapping system
doesn't have to parse C++ headers or represent the type system: the
compiler does that work for us.
Computationally intensive tasks play to the strengths of C++ and are
often impossible to implement efficiently in pure Python, while jobs
like serialization that are trivial in Python can be very difficult in
pure C++. Given the luxury of building a hybrid software system from
the ground up, we can approach design with new confidence and power.
===========
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
===========
Footnotes
===========
.. [#proto] In retrospect, it seems that "thinking hybrid" from the
ground up might have been better for the NLP system: the
natural component boundaries defined by the pure python
prototype turned out to be inappropriate for getting the
desired performance and memory footprint out of the C++ core,
which eventually caused some redesign overhead on the Python
side when the core was moved to C++.
.. [#test] We also have some reservations about driving all C++
testing through a Python interface, unless that's the only way
it will be ultimately used. Any transition across language
boundaries with such different object models can inevitably
mask bugs.
.. [#feature] These features were expressed very differently in v1 of
Boost.Python

View File

@@ -1,566 +0,0 @@
[chapter Building and Testing
[quickbook 1.7]
[authors [Abrahams, David]]
[copyright 2002 - 2015 David Abrahams, Stefan Seefeld]
[id building]
]
[/ 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)
/]
[section Requirements]
Boost.Python requires [@http://www.python.org/2.2 Python 2.2]
[footnote 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.] *or* [@http://www.python.org newer].
[endsect]
[section Background]
There are two basic models for combining C++ and Python:
* [@http://www.python.org/doc/current/ext/intro.html 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.
* [@http://www.python.org/doc/current/ext/embedding.html 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, [@http://www.python.org/doc/current/ext/extending-with-embedding.html 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()`.
[endsect]
[section No-Install Quickstart]
There is no need to “install Boost” in order to get started using
Boost.Python. These instructions use _bb_ 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 -o`\ /filename/
options to dump the build commands it executes to a file, so
you can see what your alternate build system needs to do.]
[section Basic Procedure]
1. Get Boost; see sections 1 and 2 of the _gsg_.
2. Get the `bjam` build driver. See section 5 of the _gsg_.
3. cd into the `example/quickstart/` directory of your
Boost.Python installation, which contains a small example project.
4. Invoke `bjam`. Replace the “\ `stage`\ “ argument from the
example invocation from section 5 of the _gsg_ 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:\\...\\quickstart> bjam toolset=msvc --verbose-test test
``
and on Unix variants, perhaps,
``
.../quickstart$ bjam toolset=gcc --verbose-test test
``
[note For the sake of concision, the rest of this guide will use
unix-style forward slashes in pathnames instead of the
backslashes with which Windows users may be more familiar. The forward
slashes should work everywhere except in
[@http://www.boost.org/more/getting_started/windows.html#command-prompt
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.
[endsect]
[section In Case of Trouble]
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
[link building.configuring_boost_build 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:
* The _bb_list_ for issues related to Boost.Build
* The _bp_list_ for issues specifically related to Boost.Python
[endsect]
[section In Case Everything Seemed to Work]
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_, trying out what you've
learned about the API by modifying the quickstart project.
[endsect]
[section Modifying the Example Project]
If you're content to keep your extension module forever in one
source file called `extending.cpp`, inside your Boost.Python
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
_bb_ 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.
[section 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
a. copy the entire `example/quickstart/` directory
into a new directory.
b. 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
`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
``
../../../../tools/build/src
``
to
``
/home/dave/boost_1_34_0/tools/build/src
``
and change the first path in `Jamroot` from
``
../../../..
``
to
``
/home/dave/boost_1_34_0
``
[endsect]
[section Add New or Change Names of Existing Source Files]
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`.
[endsect]
[section 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
``
python-extension extending : extending.cpp ;
``
to
``
python-extension hello : extending.cpp ;
``
and you'd edit extending.cpp, changing
``
BOOST_PYTHON_MODULE(extending)
``
to
``
BOOST_PYTHON_MODULE(hello)
``
[endsect]
[endsect]
[endsect]
[section Installing Boost.Python on your System]
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 _gsg_ 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.
[endsect]
[section Configuring Boost.Build]
As described in the [@http://www.boost.org/build/doc/html/bbv2/overview/configuration.html Boost.Build Reference Manual], a file called
`user-config.jam` in your home directory 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.
[note 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. [footnote `configure` overwrites the existing
`user-config.jam` in your home directory (if any) after making a backup of
the old version.] 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.
[section Python Configuration Parameters]
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 `using python`.
[variablelist
[[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. *not* `2.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
[link building.python_debugging_builds <python-debugging>] feature.
However, at least one Linux distribution (Ubuntu Feisty Fawn) has
a specially configured [@https://wiki.ubuntu.com/PyDbgBuilds <python-dbg>]
package that claims to use such a suffix.]]
]
[endsect]
[section Examples]
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:
``
using python : : /usr/local/python-2.6-beta/bin/python ;
``
* If you have a separate build of Python for use with a particular
toolset, you might supply that toolset in the `condition`
parameter:
``
using python ; # use for most toolsets
# Use with Intel C++ toolset
using python
: # version
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
: # includes
: # libraries
: <toolset>intel # condition
;
``
* If you have downloaded the Python sources and built both the
normal and the [link building.python_debugging_builds "python debugging"]
builds from source on Windows, you might see:
``
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
: # includes
: # libs
: <python-debugging>on ;
``
* 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:
``
# windows installation
using python ;
# cygwin installation
using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
``
when you put target-os=cygwin in your build request, it should build
with the cygwin version of python: [#flavor]_
``
bjam target-os=cygwin toolset=gcc
``
This is supposed to work the other way, too (targeting windows
python with a [@http://cygwin.com 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.
* Note that because of [@http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection
the way Boost.Build currently selects target alternatives], you might have be very
explicit in your build requests. For example, given:
``
using python : 2.5 ; # a regular windows build
using python : 2.4 : : : : <target-os>cygwin ;
``
building with
``
bjam target-os=cygwin
``
will yield an error. Instead, you'll need to write
``
bjam target-os=cygwin/python=2.4
``
[endsect]
[endsect]
[section Choosing a Boost.Python Library Binary]
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. [footnote
Information about how to identify the static and dynamic builds of Boost.Python on
[@http://boost.org/more/getting_started/windows.html#library-naming Windows] /
[@http://boost.org/more/getting_started/unix-variants.html#library-naming Unix variants]]
[section The Dynamic Binary]
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. [footnote 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.]
* 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.
[endsect]
[section The Static Binary]
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).
[endsect]
[endsect]
[section `#include` Issues]
1. 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.
2. 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.
[endsect]
[section Python Debugging Builds]
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, [footnote 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.] 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.
[endsect]
[section Testing Boost.Python]
To run the full test suite for Boost.Python, invoke `bjam` in the
`test` subdirectory of your Boost.Python distribution.
[endsect]
[section Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users]
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
[@https://docs.python.org/2/install/index.html Installing Python Modules]
to create `libpythonXX.a`, where `XX` corresponds to the major and minor
version numbers of your Python installation.
[endsect]

View File

@@ -1,83 +0,0 @@
[chapter Configuration
[quickbook 1.7]
[authors [Abrahams, David]]
[copyright 2002 - 2015 David Abrahams, Stefan Seefeld]
[id configuration]
]
[section Configuration]
[section Introduction]
[*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.
[endsect]
[section 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 [link odr ODR]. However, we know of no C++ implementations on which this particular violation is detectable or causes any problems.
[table
[[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.]]
]
[endsect]
[section Library Defined Defined Macros]
These macros are defined by *Boost.Python* and are implementation details of interest only to implementors and those porting to new platforms.
[table
[[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).]]
]
[endsect]
[endsect]

View File

@@ -1,736 +0,0 @@
[chapter Frequently Asked Questions (FAQs)
[quickbook 1.7]
[id faq]
]
[section How can I wrap a function which takes a function pointer as an argument?]
If what you're trying to do is something like this:
``
typedef boost::function<void (string s) > funcptr;
void foo(funcptr fp)
{
fp("hello,world!");
}
BOOST_PYTHON_MODULE(test)
{
def("foo",foo);
}
``
And then:
``
>>> def hello(s):
... print s
...
>>> foo(hello)
hello, world!
``
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`.
[endsect]
[section I'm getting the "attempt to return dangling reference" error.
What am I doing wrong?]
That exception is protecting you from causing a nasty crash. It usually
happens in response to some code like this:
``
period const &get_floating_frequency() const
{
return boost::python::call_method<period const &>(
m_self,"get_floating_frequency");
}
``
And you get:
``
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.
[endsect]
[section 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 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.
[endsect]
[section How can I wrap functions which take C++ containers as arguments?]
Ralf W. Grosse-Kunstleve provides these notes:
# Using the regular `class_<>` wrapper:
``
class_<std::vector<double> >("std_vector_double")
.def(...)
...
;
``
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 `scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h`
in the "scitbx" package. The file could easily be modified for
wrapping `std::vector<>` instantiations.
This type of C++/Python binding is most suitable for containers
that may contain a large number of elements (>10000).
# Using custom rvalue converters. Boost.Python "rvalue converters"
match function signatures such as:
``
void foo(std::vector<double> const &array); // pass by const-reference
void foo(std::vector<double> array); // pass by value
``
Some custom rvalue converters are implemented in the file
`scitbx/include/scitbx/boost_python/container_conversions.h`
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
`scitbx/array_family/boost_python/regression_test_module.cpp`
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:
C++:
``
void foo(std::vector<double> &array)
{
for(std::size_t i=0;i&lt;array.size();i++) {
array[i] *= 2;
}
}
``
Python: [python]
``
>>> l = [1, 2, 3]
>>> foo(l)
>>> print l
[2, 4, 6]
``
Custom lvalue converters require changes to the Boost.Python core library
and are currently not available.
P.S.:
The "scitbx" files referenced above are available via anonymous
CVS:
``
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
``
[endsect]
[section fatal error C1204:Compiler limit:internal structure overflow]
[*Q:] /I get this error message when compiling a large source file. What can I do?/
[*A:] You have two choices:
# Upgrade your compiler (preferred)
# Break your source file up into multiple translation units.
`my_module.cpp`: [c++]
``
...
void more_of_my_module();
BOOST_PYTHON_MODULE(my_module)
{
def("foo", foo);
def("bar", bar);
...
more_of_my_module();
}
``
`more_of_my_module.cpp`:
``
void more_of_my_module()
{
def("baz", baz);
...
}
``
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:
`more_of_my_class.cpp`:
``
void more_of_my_class(class&lt;my_class&gt;&amp; x)
{
x
.def("baz", baz)
.add_property("xx", &my_class::get_xx, &my_class::set_xx)
;
...
}
``
[endsect]
[section How do I debug my Python extensions?]
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)
``
]
[h2 Debugging extensions through Boost.Build]
If you are launching your extension module tests with _bb_ 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.
[endsect]
[section 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 use `p1.__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.
[endsect]
[section 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:
``./configure --enable-framework
make
make frameworkinstall``
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__) &amp;&amp; defined(__APPLE_CC__) &amp;&amp; __APPLE_CC__ == 1493
bool dummy_;
#endif
// now your member data, e.g.
double x;
int j;
// etc.
};
``
[endsect]
[section How can I find the existing PyObject that holds a C++ object?]
[: "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
`X`\ s 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.
[endsect]
[section How can I wrap a function which needs to take ownership of a raw pointer?]
[*Q:] 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:
``
void b_insert(B &b, std::auto_ptr<A> a)
{
b.insert(a.get());
a.release();
}
``
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.
[endsect]
[section Compilation takes too much time and eats too much memory!
What can I do to make it faster?]
Please refer to the `Reducing Compiling Time` section in the _tutorial_.
[endsect]
[section How do I create sub-packages using Boost.Python?]
Please refer to the `Creating Packages` section in the _tutorial_.
[endsect]
[section 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:
``
#include <boost/python.hpp>
using namespace boost::python;
class FXThread
{
public:
bool setAutoDelete(bool doso) throw();
};
void Export_FXThread()
{
class_< FXThread >("FXThread")
.def("setAutoDelete", &amp;FXThread::setAutoDelete)
;
}
``
The bug is related to the `throw()` modifier.
As a workaround cast off the modifier. E.g.:
``
.def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)
``
(The bug has been reported to Microsoft.)
[endsect]
[section How can I automatically convert my custom string type to and from a Python string?]
/Ralf W. Grosse-Kunstleve provides these notes:/
Below is a small, self-contained demo extension module that shows
how to do this. Here is the corresponding trivial test:
``
import custom_string
assert custom_string.hello() == "Hello world."
assert custom_string.size("california") == 10
``
If you look at the code you will find:
* 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.
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/to_python_converter.hpp>
namespace sandbox { namespace {
class custom_string
{
public:
custom_string() {}
custom_string(std::string const &value) : value_(value) {}
std::string const &value() const { return value_; }
private:
std::string value_;
};
struct custom_string_to_python_str
{
static PyObject* convert(custom_string const &s)
{
return boost::python::incref(boost::python::object(s.value()).ptr());
}
};
struct custom_string_from_python_str
{
custom_string_from_python_str()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<custom_string>());
}
static void* convertible(PyObject* obj_ptr)
{
if (!PyString_Check(obj_ptr)) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
const char* value = PyString_AsString(obj_ptr);
if (value == 0) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<custom_string>*)
data)->storage.bytes;
new (storage) custom_string(value);
data->convertible = storage;
}
};
custom_string hello() { return custom_string("Hello world."); }
std::size_t size(custom_string const &s) { return s.value().size(); }
void init_module()
{
using namespace boost::python;
boost::python::to_python_converter<
custom_string,
custom_string_to_python_str>();
custom_string_from_python_str();
def("hello", hello);
def("size", size);
}
}} // namespace sandbox::<anonymous>
BOOST_PYTHON_MODULE(custom_string)
{
sandbox::init_module();
}
``
[endsect]
[section 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:
``
.add_property("bar", make_getter(&foo::bar, return_internal_reference()))
``
Similarly, `def_readwrite("bar",&foo::bar)` is
equivalent to:
``
.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
make_setter(&foo::bar, return_internal_reference())
``
In order to define return value policies compatible with the
custom conversions replace `def_readonly()` and
`def_readwrite()` by `add_property()`. E.g.:
``
.add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
make_setter(&foo::bar, return_value_policy<return_by_value>()))
``
[endsect]
[section 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 [@http://sourceforge.net/projects/tnfox/ this]
SourceForge project location.
[endsect]

View File

@@ -1,38 +0,0 @@
[chapter Glossary
[quickbook 1.7]
[id glossary]
]
[variablelist
[[arity [#arity]]
[The number of argumnts accepted by a function or member function.
Unless otherwise specified, the hidden `this` argument to member
functions is not counted when specifying arity.]]
[[ntbs [#ntbs]]
[Null-Terminated Byte String, or 'C'-string. C++ string literals are *ntbs*\ es.
An *ntbs* must never be null.]]
[[raise [#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 [@http://www.python.org/doc/current/api/exceptionHandling.html Python/'C' API],
and `throw_error_already_set()` is called.]]
[[POD [#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 [#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.]]
]

View File

@@ -1,19 +0,0 @@
[library Boost.Python
[quickbook 1.3]
[authors [Abrahams, David], [Seefeld, Stefan]]
[copyright 2002 2003 2004 2005 2015 David Abrahams, Stefan Seefeld]
[category inter-language support]
[id python]
[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 1.3 ]
[include preface.qbk]

View File

@@ -1,186 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
<title>Boost.Python Internals Boost</title>
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
</head>
<body>
<div class="document" id="boost-python-internals-logo">
<h1 class="title"><a class="reference" href="index.html">Boost.Python</a> Internals <a class="reference" href="../../../index.htm"><img alt="Boost" src="../../../boost.png" /></a></h1>
<div class="section" id="a-conversation-between-brett-calcott-and-david-abrahams">
<h1><a name="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</a></h1>
<table class="field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams and Brett Calcott 2003. See
accompanying <a class="reference" href="../../../LICENSE_1_0.txt">license</a> for terms of use.</td>
</tr>
</tbody>
</table>
<p>In both of these cases, I'm quite capable of reading code - but the
thing I don't get from scanning the source is a sense of the
architecture, both structurally, and temporally (er, I mean in what
order things go on).</p>
<ol class="arabic">
<li><p class="first">What happens when you do the following:</p>
<pre class="literal-block">
struct boring {};
...etc...
class_&lt;boring&gt;(&quot;boring&quot;)
;
</pre>
</li>
</ol>
<p>There seems to be a fair bit going on.</p>
<blockquote>
<ul class="simple">
<li>Python needs a new ClassType to be registered.</li>
<li>We need to construct a new type that can hold our boring struct.</li>
<li>Inward and outward converters need to be registered for the type.</li>
</ul>
</blockquote>
<p>Can you gesture in the general direction where these things are done?</p>
<blockquote>
<p>I only have time for a &quot;off-the-top-of-my-head&quot; answer at the moment;
I suggest you step through the code with a debugger after reading this
to see how it works, fill in details, and make sure I didn't forget
anything.</p>
<blockquote>
<p>A new (Python) subclass of Boost.Python.Instance (see
libs/python/src/object/class.cpp) is created by invoking
Boost.Python.class, the metatype:</p>
<pre class="literal-block">
&gt;&gt;&gt; boring = Boost.Python.class(
... 'boring'
... , bases_tuple # in this case, just ()
... , {
... '__module__' : module_name
... , '__doc__' : doc_string # optional
... }
... )
</pre>
<p>A handle to this object is stuck in the m_class_object field
of the registration associated with <tt class="literal"><span class="pre">typeid(boring)</span></tt>. The
registry will keep that object alive forever, even if you
wipe out the 'boring' attribute of the extension module
(probably not a good thing).</p>
<p>Because you didn't specify <tt class="literal"><span class="pre">class&lt;boring,</span> <span class="pre">non_copyable,</span>
<span class="pre">...&gt;</span></tt>, a to-python converter for boring is registered which
copies its argument into a value_holder held by the the
Python boring object.</p>
<p>Because you didn't specify <tt class="literal"><span class="pre">class&lt;boring</span> <span class="pre">...&gt;(no_init)</span></tt>,
an <tt class="literal"><span class="pre">__init__</span></tt> function object is added to the class
dictionary which default-constructs a boring in a
value_holder (because you didn't specify some smart pointer
or derived wrapper class as a holder) held by the Python
boring object.</p>
<p><tt class="literal"><span class="pre">register_class_from_python</span></tt> is used to register a
from-python converter for <tt class="literal"><span class="pre">shared_ptr&lt;boring&gt;</span></tt>.
<tt class="literal"><span class="pre">boost::shared_ptr</span></tt>s are special among smart pointers
because their Deleter argument can be made to manage the
whole Python object, not just the C++ object it contains, no
matter how the C++ object is held.</p>
<p>If there were any <tt class="literal"><span class="pre">bases&lt;&gt;</span></tt>, we'd also be registering the
relationship between these base classes and boring in the
up/down cast graph (<tt class="literal"><span class="pre">inheritance.[hpp/cpp]</span></tt>).</p>
<p>In earlier versions of the code, we'd be registering lvalue
from-python converters for the class here, but now
from-python conversion for wrapped classes is handled as a
special case, before consulting the registry, if the source
Python object's metaclass is the Boost.Python metaclass.</p>
<p>Hmm, that from-python converter probably ought to be handled
the way class converters are, with no explicit conversions
registered.</p>
</blockquote>
</blockquote>
<ol class="arabic" start="2">
<li><p class="first">Can you give a brief overview of the data structures that are
present in the registry</p>
<blockquote>
<p>The registry is simple: it's just a map from typeid -&gt;
registration (see boost/python/converter/registrations.hpp).
<tt class="literal"><span class="pre">lvalue_chain</span></tt> and <tt class="literal"><span class="pre">rvalue_chain</span></tt> are simple endogenous
linked lists.</p>
<p>If you want to know more, just ask.</p>
<p>If you want to know about the cast graph, ask me something specific in
a separate message.</p>
</blockquote>
<p>and an overview of the process that happens as a type makes its
way from c++ to python and back again.</p>
</li>
</ol>
<blockquote>
<p>Big subject. I suggest some background reading: look for relevant
info in the LLNL progress reports and the messages they link to.
Also,</p>
<blockquote>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a></p>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-December/003115.html">http://mail.python.org/pipermail/c++-sig/2002-December/003115.html</a></p>
<p><a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a></p>
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-July/001755.html">http://mail.python.org/pipermail/c++-sig/2002-July/001755.html</a></p>
</blockquote>
<p>from c++ to python:</p>
<blockquote>
<p>It depends on the type and the call policies in use or, for
<tt class="literal"><span class="pre">call&lt;&gt;(...)</span></tt>, <tt class="literal"><span class="pre">call_method&lt;&gt;(...)</span></tt>, or <tt class="literal"><span class="pre">object(...)</span></tt>, if
<tt class="literal"><span class="pre">ref</span></tt> or <tt class="literal"><span class="pre">ptr</span></tt> is used. There are also two basic
categories to to-python conversion, &quot;return value&quot; conversion
(for Python-&gt;C++ calls) and &quot;argument&quot; conversion (for
C++-&gt;Python calls and explicit <tt class="literal"><span class="pre">object()</span></tt> conversions). The
behavior of these two categories differs subtly in various ways
whose details I forget at the moment. You can probably find
the answers in the above references, and certainly in the code.</p>
<p>The &quot;default&quot; case is by-value (copying) conversion, which uses
to_python_value as a to-python converter.</p>
<blockquote>
<p>Since there can sensibly be only one way to convert any type
to python (disregarding the idea of scoped registries for the
moment), it makes sense that to-python conversions can be
handled by specializing a template. If the type is one of
the types handled by a built-in conversion
(builtin_converters.hpp), the corresponding template
specialization of to_python_value gets used.</p>
<p>Otherwise, to_python_value uses the <tt class="literal"><span class="pre">m_to_python</span></tt>
function in the registration for the C++ type.</p>
</blockquote>
<p>Other conversions, like by-reference conversions, are only
available for wrapped classes, and are requested explicitly by
using <tt class="literal"><span class="pre">ref(...)</span></tt>, <tt class="literal"><span class="pre">ptr(...)</span></tt>, or by specifying different
CallPolicies for a call, which can cause a different to-python
converter to be used. These conversions are never registered
anywhere, though they do need to use the registration to find
the Python class corresponding to the C++ type being referred
to. They just build a new Python instance and stick the
appropriate Holder instance in it.</p>
</blockquote>
<p>from python to C++:</p>
<blockquote>
<p>Once again I think there is a distinction between &quot;return value&quot;
and &quot;argument&quot; conversions, and I forget exactly what that is.</p>
<p>What happens depends on whether an lvalue conversion is needed
(see <a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a>)
All lvalue conversions are also registered in a type's rvalue
conversion chain, since when an rvalue will do, an lvalue is
certainly good enough.</p>
<p>An lvalue conversion can be done in one step (just get me the
pointer to the object - it can be <tt class="literal"><span class="pre">NULL</span></tt> if no conversion is
possible) while an rvalue conversion requires two steps to
support wrapped function overloading and multiple converters for
a given C++ target type: first tell me if a conversion is
possible, then construct the converted object as a second step.</p>
</blockquote>
</blockquote>
</div>
</div>
<hr class="footer"/>
<div class="footer">
<a class="reference" href="internals.rst">View document source</a>.
Generated on: 2003-09-12 14:51 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>
</body>
</html>

View File

@@ -1,182 +0,0 @@
===================================
Boost.Python_ Internals |(logo)|__
===================================
.. |(logo)| image:: ../../../boost.png
:alt: Boost
:class: boost-logo
__ ../../../index.htm
.. _`Boost.Python`: index.html
.. _license: ../../../LICENSE_1_0.txt
-------------------------------------------------------
A conversation between Brett Calcott and David Abrahams
-------------------------------------------------------
:copyright: Copyright David Abrahams and Brett Calcott 2003. See
accompanying license_ for terms of use.
In both of these cases, I'm quite capable of reading code - but the
thing I don't get from scanning the source is a sense of the
architecture, both structurally, and temporally (er, I mean in what
order things go on).
1) What happens when you do the following::
struct boring {};
...etc...
class_<boring>("boring")
;
There seems to be a fair bit going on.
- Python needs a new ClassType to be registered.
- We need to construct a new type that can hold our boring struct.
- Inward and outward converters need to be registered for the type.
Can you gesture in the general direction where these things are done?
I only have time for a "off-the-top-of-my-head" answer at the moment;
I suggest you step through the code with a debugger after reading this
to see how it works, fill in details, and make sure I didn't forget
anything.
A new (Python) subclass of Boost.Python.Instance (see
libs/python/src/object/class.cpp) is created by invoking
Boost.Python.class, the metatype::
>>> boring = Boost.Python.class(
... 'boring'
... , bases_tuple # in this case, just ()
... , {
... '__module__' : module_name
... , '__doc__' : doc_string # optional
... }
... )
A handle to this object is stuck in the m_class_object field
of the registration associated with ``typeid(boring)``. The
registry will keep that object alive forever, even if you
wipe out the 'boring' attribute of the extension module
(probably not a good thing).
Because you didn't specify ``class<boring, non_copyable,
...>``, a to-python converter for boring is registered which
copies its argument into a value_holder held by the the
Python boring object.
Because you didn't specify ``class<boring ...>(no_init)``,
an ``__init__`` function object is added to the class
dictionary which default-constructs a boring in a
value_holder (because you didn't specify some smart pointer
or derived wrapper class as a holder) held by the Python
boring object.
``register_class_from_python`` is used to register a
from-python converter for ``shared_ptr<boring>``.
``boost::shared_ptr``\ s are special among smart pointers
because their Deleter argument can be made to manage the
whole Python object, not just the C++ object it contains, no
matter how the C++ object is held.
If there were any ``bases<>``, we'd also be registering the
relationship between these base classes and boring in the
up/down cast graph (``inheritance.[hpp/cpp]``).
In earlier versions of the code, we'd be registering lvalue
from-python converters for the class here, but now
from-python conversion for wrapped classes is handled as a
special case, before consulting the registry, if the source
Python object's metaclass is the Boost.Python metaclass.
Hmm, that from-python converter probably ought to be handled
the way class converters are, with no explicit conversions
registered.
2) Can you give a brief overview of the data structures that are
present in the registry
The registry is simple: it's just a map from typeid ->
registration (see boost/python/converter/registrations.hpp).
``lvalue_chain`` and ``rvalue_chain`` are simple endogenous
linked lists.
If you want to know more, just ask.
If you want to know about the cast graph, ask me something specific in
a separate message.
and an overview of the process that happens as a type makes its
way from c++ to python and back again.
Big subject. I suggest some background reading: look for relevant
info in the LLNL progress reports and the messages they link to.
Also,
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
http://aspn.activestate.com/ASPN/Mail/Message/1280898
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
from c++ to python:
It depends on the type and the call policies in use or, for
``call<>(...)``, ``call_method<>(...)``, or ``object(...)``, if
``ref`` or ``ptr`` is used. There are also two basic
categories to to-python conversion, "return value" conversion
(for Python->C++ calls) and "argument" conversion (for
C++->Python calls and explicit ``object()`` conversions). The
behavior of these two categories differs subtly in various ways
whose details I forget at the moment. You can probably find
the answers in the above references, and certainly in the code.
The "default" case is by-value (copying) conversion, which uses
to_python_value as a to-python converter.
Since there can sensibly be only one way to convert any type
to python (disregarding the idea of scoped registries for the
moment), it makes sense that to-python conversions can be
handled by specializing a template. If the type is one of
the types handled by a built-in conversion
(builtin_converters.hpp), the corresponding template
specialization of to_python_value gets used.
Otherwise, to_python_value uses the ``m_to_python``
function in the registration for the C++ type.
Other conversions, like by-reference conversions, are only
available for wrapped classes, and are requested explicitly by
using ``ref(...)``, ``ptr(...)``, or by specifying different
CallPolicies for a call, which can cause a different to-python
converter to be used. These conversions are never registered
anywhere, though they do need to use the registration to find
the Python class corresponding to the C++ type being referred
to. They just build a new Python instance and stick the
appropriate Holder instance in it.
from python to C++:
Once again I think there is a distinction between "return value"
and "argument" conversions, and I forget exactly what that is.
What happens depends on whether an lvalue conversion is needed
(see http://mail.python.org/pipermail/c++-sig/2002-May/001023.html)
All lvalue conversions are also registered in a type's rvalue
conversion chain, since when an rvalue will do, an lvalue is
certainly good enough.
An lvalue conversion can be done in one step (just get me the
pointer to the object - it can be ``NULL`` if no conversion is
possible) while an rvalue conversion requires two steps to
support wrapped function overloading and multiple converters for
a given C++ target type: first tell me if a conversion is
possible, then construct the converted object as a second step.

View File

@@ -1,222 +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)
How Runtime Polymorphism is expressed in Boost.Python:
-----------------------------------------------------
struct A { virtual std::string f(); virtual ~A(); };
std::string call_f(A& x) { return x.f(); }
struct B { virtual std::string f() { return "B"; } };
struct Bcb : B
{
Bcb(PyObject* self) : m_self(self) {}
virtual std::string f() { return call_method<std::string>(m_sef, "f"); }
static std::string f_default(B& b) { return b.B::f(); }
PyObject* m_self;
};
struct C : B
{
virtual std::string f() { return "C"; }
};
>>> class D(B):
... def f():
... return 'D'
...
>>> class E(B): pass
...
When we write, "invokes B::f non-virtually", we mean:
void g(B& x) { x.B::f(); }
This will call B::f() regardless of the dynamic type of x. Any other
way of invoking B::f, including through a function pointer, is a
"virtual invocation", and will call the most-derived override of f().
Case studies
C++\Python class
\___A_____B_____C_____D____E___
|
A | 1
|
B | 2 3
|
Bcb | 4 5 6
|
C | 7 8
|
1. Simple case
2. Python A holds a B*. Probably won't happen once we have forced
downcasting.
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: A.f invokes A::f() (virtually or otherwise)
3. Python B holds a B*.
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f (virtually or otherwise)
4. B constructed from Python
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f non-virtually. Bcb::f invokes B::f
non-virtually.
Question: Does it help if we arrange for Python B construction to
build a true B object? Then this case doesn't arise.
5. D is a Python class derived from B
Requires:
x.f() -> 'D'
call_f(x) -> 'D'
Implies: Bcb::f must invoke call_method to look up the Python
method override, otherwise call_f wouldn't work.
6. E is like D, but doesn't override f
Requires:
x.f() -> 'B'
call_f(x) -> 'B'
Implies: B.f invokes B::f non-virtually. If it were virtual, x.f()
would cause infinite recursion, because we've already
determined that Bcb::f must invoke call_method to look up
the Python method override.
7. Python B object holds a C*
Requires:
x.f() -> 'C'
call_f(x) -> 'C'
Implies: B.f invokes B::f virtually.
8. C object constructed from Python
Requires:
x.f() -> 'C'
call_f(x) -> 'C'
Implies: nothing new.
------
Total implications:
2: A.f invokes A::f() (virtually or otherwise)
3: B.f invokes B::f (virtually or otherwise)
4: B.f invokes B::f non-virtually. Bcb::f invokes B::f non-virtually
6: B.f invokes B::f non-virtually.
7: B.f invokes B::f virtually.
5: Bcb::f invokes call_method to look up the Python method
Though (4) is avoidable, clearly 6 and 7 are not, and they
conflict. The implication is that B.f must choose its behavior
according to the type of the contained C++ object. If it is Bcb, a
non-virtual call to B::f must occur. Otherwise, a virtual call to B::f
must occur. This is essentially the same scheme we had with
Boost.Python v1.
Note: in early versions of Boost.Python v1, we solved this problem by
introducing a new Python class in the hierarchy, so that D and E
actually derive from a B', and B'.f invokes B::f non-virtually, while
B.f invokes B::f virtually. However, people complained about the
artificial class in the hierarchy, which was revealed when they tried
to do normal kinds of Python introspection.
-------
Assumption: we will have a function which builds a virtual function
dispatch callable Python object.
make_virtual_function(pvmf, default_impl, call_policies, dispatch_type)
Pseudocode:
Get first argument from Python arg tuple
if it contains dispatch_type
call default_impl
else
call through pvmf
Open questions:
1. What about Python multiple inheritance? Do we have the right
check in the if clause above?
A: Not quite. The correct test looks like:
Deduce target type of pvmf, i.e. T in R(T::*)(A1...AN).
Find holder in first argument which holds T
if it holds dispatch_type...
2. Can we make this more efficient?
The current "returning" mechanism will look up a holder for T
again. I don't know if we know how to avoid that.
OK, the solution involves reworking the call mechanism. This is
neccesary anyway in order to enable wrapping of function objects.
It can result in a reduction in the overall amount of source code,
because returning<> won't need to be specialized for every
combination of function and member function... though it will still
need a void specialization. We will still need a way to dispatch to
member functions through a regular function interface. mem_fn is
almost the right tool, but it only goes up to 8
arguments. Forwarding is tricky if you don't want to incur copies.
I think the trick is to use arg_from_python<T>::result_type for each
argument to the forwarder.
Another option would be to use separate function, function object,
and member function dispatchers. Once you know you have a member
function, you don't need cv-qualified overloads to call it.
Hmm, while we're at this, maybe we should solve the write-back
converter problem. Can we do it? Maybe not. Ralf doesn't want to
write special write-back functions here, does he? He wants the
converter to do the work automatically. We could add
cleanup/destructor registration. That would relieve the client from
having accessible destructors for types which are being converted by
rvalue. I'm not sure that this will really save any code,
however. It rather depends on the linker, doesn't it? I wonder if
this can be done in a backwards-compatible fashion by generating the
delete function when it's not supplied?

View File

@@ -1,26 +0,0 @@
[preface Introduction
[quickbook 1.6]
]
[section Synopsis]
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:
* References and Pointers
* Globally Registered Type Coercions
* Automatic Cross-Module Type Conversions
* Efficient Function Overloading
* C++ to Python Exception Translation
* Default Arguments
* Keyword Arguments
* Manipulating Python objects in C++
* Exporting C++ Iterators as Python Iterators
* Documentation Strings
The development of these features was funded in part by grants to Boost Consulting from the Lawrence Livermore National Laboratories and by the Computational Crystallography Initiative at Lawrence Berkeley National Laboratories.
[endsect]
[section Articles]
"Building Hybrid Systems With Boost Python", by Dave Abrahams and Ralf W. Grosse-Kunstleve (PDF)
[endsect]

View File

@@ -1,64 +0,0 @@
[book Boost.Python
[quickbook 1.7]
[authors [Abrahams, David], [Seefeld, Stefan]]
[copyright 2002 - 2015 David Abrahams, Stefan Seefeld]
[category inter-language support]
[id python]
[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])
]
]
[def _boost_ [@http://www.boost.org Boost]]
[def _bb_ [@http://www.boost.org/build Boost.Build]]
[def _bb_list_ [@http://www.boost.org/more/mailing_lists.htm#jamboost Boost.Build mailing list]]
[def _bp_list_ [@http://www.boost.org/more/mailing_lists.htm#cplussig Boost.Python mailing list]]
[def _tutorial_ [@tutorial/index.html Tutorial]]
[def _reference_ [@reference/index.html Reference Manual]]
[def _gsg_ Boost [@http://www.boost.org/more/getting_started/ Getting Started Guide]]
[def _extending_ [@https://docs.python.org/2/extending/extending.html extending]]
[def _embedding_ [@https://docs.python.org/2/extending/embedding.html embedding]]
[h2 Synopsis]
Welcome to Boost.Python, a C++ library which enables seamless interoperability between C++ and the Python programming language. The library includes support for:
* References and Pointers
* Globally Registered Type Coercions
* Automatic Cross-Module Type Conversions
* Efficient Function Overloading
* C++ to Python Exception Translation
* Default Arguments
* Keyword Arguments
* Manipulating Python objects in C++
* Exporting C++ Iterators as Python Iterators
* Documentation Strings
The development of these features was funded in part by grants to `Boost Consulting` from the [@http://www.llnl.gov Lawrence Livermore National Laboratories] and by the [@http://cci.lbl.gov Computational Crystallography Initiative] at Lawrence Berkeley National Laboratories.
[section Contents]
* _tutorial_
* [link building Building and Testing]
* _reference_
* [link configuration Configuration Information]
* [link glossary Glossary]
* [link support Support Resources]
* [link faq Frequently Asked Questions (FAQs)]
[endsect]
[h2 Articles]
[@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]

View File

@@ -1,21 +0,0 @@
[book Boost.Python Reference Manual
[quickbook 1.7]
[authors [Abrahams, David], [Seefeld, Stefan]]
[copyright 2002 2003 2004 2005 2015 David Abrahams, Stefan Seefeld]
[id reference]
[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]
]
]
[include reference/concepts.qbk]
[include reference/components.qbk]
[include reference/objects.qbk]
[include reference/functions.qbk]
[include reference/conversion.qbk]
[include reference/embedding.qbk]
[include reference/utility.qbk]
[include reference/topics.qbk]
[include glossary.qbk]

View File

@@ -1,62 +0,0 @@
[section boost/python/args.hpp]
[section Introduction]
Supplies a family of overloaded functions for specifying argument keywords for wrapped C++ functions.
[section keyword-expressions]
A keyword-expression results in an object which holds a sequence of [link ntbs]\ es, 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
[endsect]
[endsect]
[section Class `arg`]
The objects of class arg are keyword-expressions holding one keyword ( size one )
``
namespace boost { namespace python
{
struct arg
{
template <class T>
arg &operator = (T const &value);
explicit arg (char const *name){elements[0].name = name;}
};
}}
``
[endsect]
[section Class `arg` constructor]
``arg(char const* name);``
[variablelist
[[Requires][The argument must be a [link ntbs].]]
[[Effects][Constructs an arg object holding a keyword with name name.]]
]
[endsect]
[section Class `arg` operator=]
``template <class T> arg &operator = (T const &value);``
[variablelist
[[Requires][The argument must convertible to python.]]
[[Effects][Assigns default value for the keyword.]]
[[Returns][Reference to `this`.]]
]
[endsect]
[section Keyword-expression operator,]
``
keyword-expression operator , (keyword-expression, const arg &kw) const
keyword-expression operator , (keyword-expression, const char *name) const;
``
[variablelist
[[Requires][The argument name must be a [link ntbs].]]
[[Effects][Extends the keyword-expression argument with one more keyword.]]
[[Returns][The extended keyword-expression.]]
]
[endsect]
[section Example]
``
#include <boost/python/def.hpp>
using namespace boost::python;
int f(double x, double y, double z=0.0, double w=1.0);
BOOST_PYTHON_MODULE(xxx)
{
def("f", f, (arg("x"), "y", arg("z")=0.0, arg("w")=1.0));
}
``
[endsect]
[endsect]

View File

@@ -1,26 +0,0 @@
[section boost/python/call.hpp]
[section Introduction]
<boost/python/call.hpp> defines the call family of overloaded function templates, used to invoke Python callable objects from C++.
[endsect]
[section Function `call`]
``
template <class R, class A1, class A2, ... class An>
R call(PyObject* callable, A1 const&, A2 const&, ... An const&)
``
[variablelist
[[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. ]]
]
[endsect]
[section Example]
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.
``
double apply2(PyObject* func, double x, double y)
{
return boost::python::call<double>(func, x, y);
}
``
[endsect]
[endsect]

View File

@@ -1,80 +0,0 @@
[section boost/python/call_method.hpp]
[section Introduction]
<boost/python/call_method.hpp> defines the call_method family of overloaded function templates, used to invoke callable attributes of Python objects from C++.
[endsect]
[section Function `call_method`]
``
template <class R, class A1, class A2, ... class An>
R call_method(PyObject* self, char const* method, A1 const&, A2 const&, ... An const&)
``
[variablelist
[[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.]]
]
[endsect]
[section Example]
The following C++ illustrates the use of `call_method` in wrapping a class with a virtual function that can be overridden in Python:
C++ Module Definition
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/utility.hpp>
#include <cstring>
// class to be wrapped
class Base
{
public:
virtual char const* class_name() const { return "Base"; }
virtual ~Base();
};
bool is_base(Base* b)
{
return !std::strcmp(b->class_name(), "Base");
}
// Wrapper code begins here
using namespace boost::python;
// Callback class
class Base_callback : public Base
{
public:
Base_callback(PyObject* self) : m_self(self) {}
char const* class_name() const { return call_method<char const*>(m_self, "class_name"); }
char const* Base_name() const { return Base::class_name(); }
private:
PyObject* const m_self;
};
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
def("is_base", is_base);
class_<Base,Base_callback, noncopyable>("Base")
.def("class_name", &Base_callback::Base_name)
;
}
``
Python code:
``
>>> from my_module import *
>>> class Derived(Base):
... def __init__(self):
... Base.__init__(self)
... def class_name(self):
... return self.__class__.__name__
...
>>> is_base(Base()) # calls the class_name() method from C++
1
>>> is_base(Derived())
0
``
[endsect]
[endsect]

View File

@@ -1,65 +0,0 @@
[section Calling Python Functions and Methods]
[section Introduction]
The simplest way to call a Python function from C++, given an [link object_wrappers.boost_python_object_hpp.class_object `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 [link object_wrappers.boost_python_object_hpp.class_object `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 [link object_wrappers.boost_python_object_hpp.class_object `object`] instance, `Boost.Python` provides two families of function templates, [link function_invocation_and_creation.boost_python_call_hpp.function_call `call`] and [link function_invocation_and_creation.boost_python_call_method_hpp.function_call_method `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:
``call<ResultType>(callable_object, a1, a2... aN);``
Calling a method of a Python object is similarly easy:
``call_method<ResultType>(self_object, "method-name", a1, a2... aN);``
This comparitively low-level interface is the one you'll use when implementing C++ virtual functions that can be overridden in Python.
[endsect]
[section Argument Handling]
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 [link function_invocation_and_creation.boost_python_ptr_hpp.functions `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".
[table
[[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.]]
[[boost::reference_wrapper<T>][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!]]
[[pointer_wrapper<T>][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!]]
]
[endsect]
[section Result Handling]
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.
[endsect]
[section Rationale]
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 this is dealt with by:
# lifting the compile-time restriction on `char const *` 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.
[endsect]
[endsect]

View File

@@ -1,308 +0,0 @@
[section boost/python/class.hpp]
[section Introduction]
`<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.
[endsect]
[section 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.
[table
[[Template Parameter][Requirements][Semantics][Default]]
[[`T`][A class type.][The class being wrapped][]]
[[Bases]
[A specialization of [link high_level_components.boost_python_class_hpp.class_template_bases_t1_t2_tn bases<...>] which specifies previously-exposed C++ base classes of `T`.]
[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`.][[link high_level_components.boost_python_class_hpp.class_template_bases_t1_t2_tn bases<>]]]
[[HeldType][Must be `T`, a class derived from `T`, or a [link concepts.dereferenceable.concept_requirements 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 [link function_invocation_and_creation.boost_python_ptr_hpp.functions ptr], `ref`, or [link concepts.callpolicies Call Policies] such as [link function_invocation_and_creation.models_of_callpolicies.boost_python_return_internal_ref.class_template_return_internal_r return_internal_reference]. More details below.][`T`]]
[[NonCopyable][If supplied, must be `boost::noncopyable`.][Suppresses automatic registration of `to_python` conversions which copy `T` instances. Required when `T` has no publicly-accessible copy constructor.][An unspecified type other than boost::noncopyable.]]
]
[section HeldType Semantics]
# 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 [link high_level_components.boost_python_init_hpp.introduction.init_expressions init-expression] passed to [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu 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 [link utility_and_infrastructure.boost_python_has_back_reference_.class_template_has_back_referenc has_back_reference<T>].
[endsect]
[section Class template `class_` synopsis]
``
namespace boost { namespace python
{
template <class T
, class Bases = bases<>
, class HeldType = T
, class NonCopyable = unspecified
>
class class_ : public object
{
// Constructors with default __init__
class_(char const* name);
class_(char const* name, char const* docstring);
// Constructors, specifying non-default __init__
template <class Init>
class_(char const* name, Init);
template <class Init>
class_(char const* name, char const* docstring, Init);
// Exposing additional __init__ functions
template <class Init>
class_& def(Init);
// defining methods
template <class F>
class_& def(char const* name, F f);
template <class Fn, class A1>
class_& def(char const* name, Fn fn, A1 const&);
template <class Fn, class A1, class A2>
class_& def(char const* name, Fn fn, A1 const&, A2 const&);
template <class Fn, class A1, class A2, class A3>
class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
// declaring method as static
class_& staticmethod(char const* name);
// exposing operators
template <unspecified>
class_& def(detail::operator_<unspecified>);
// Raw attribute modification
template <class U>
class_& setattr(char const* name, U const&);
// exposing data members
template <class D>
class_& def_readonly(char const* name, D T::*pm);
template <class D>
class_& def_readwrite(char const* name, D T::*pm);
// exposing static data members
template <class D>
class_& def_readonly(char const* name, D const& d);
template <class D>
class_& def_readwrite(char const* name, D& d);
// property creation
template <class Get>
void add_property(char const* name, Get const& fget, char const* doc=0);
template <class Get, class Set>
void add_property(
char const* name, Get const& fget, Set const& fset, char const* doc=0);
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);
// pickle support
template <typename PickleSuite>
self& def_pickle(PickleSuite const&);
self& enable_pickling();
};
}}
``
[endsect]
[section Class template `class_` constructors]
``
class_(char const* name);
class_(char const* name, char const* docstring);
template <class Init>
class_(char const* name, Init init_spec);
template <class Init>
class_(char const* name, char const* docstring, Init init_spec);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules]. If docstring is supplied, it must be an [link ntbs]. If `init_spec` is supplied, it must be either the special enumeration constant `no_init` or an [link high_level_components.boost_python_init_hpp.introduction.init_expressions init-expression] compatible with `T`.]]
[[Effects][Constructs a `class_` object holding a Boost.Python extension class named name. The named attribute of the [link high_level_components.boost_python_scope_hpp.introduction 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.]]
]
[endsect]
[section Class template `class_` modifier functions]
``
template <class Init>
class_& def(Init init_expr);
``
[variablelist
[[Requires][`init_expr` is the result of an [link high_level_components.boost_python_init_hpp.introduction.init_expressions init-expression] compatible with `T`.]]
[[Effects][For each [link high_level_components.boost_python_init_hpp.introduction.init_expressions valid prefix] `P` 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 [link high_level_components.boost_python_init_hpp.introduction.init_expressions 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.]]
]
``
template <class F>
class_& def(char const* name, Fn fn);
template <class Fn, class A1>
class_& def(char const* name, Fn fn, A1 const& a1);
template <class Fn, class A1, class A2>
class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2);
template <class Fn, class A1, class A2, class A3>
class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].
* If a1 is the result of an [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions overload-dispatch-expression], only the second form is allowed and fn must be a pointer to function or pointer to member function whose [link arity] is the same as A1's [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions maximum arity].
[*Effects:] For each prefix `P` of `Fn`\ 's sequence of argument types, beginning with the one whose length is `A1`\ 's [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions 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] [link object_wrappers.boost_python_object_hpp.class_object 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 [@http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-6 callable].
[table
[[Mnemonic Name][Requirements/Type properties][Effects]]
[[docstring][Any [link ntbs]][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.]]
[[policies][A model of [link concepts.callpolicies CallPolicies]][A copy will be used as the call policies of the resulting method overload.]]
[[keywords][The result of a [link function_invocation_and_creation.boost_python_args_hpp.introduction.keyword_expressions keyword-expression] specifying no more arguments than the [link arity] of fn.][A copy will be used as the call policies of the resulting method overload.]]
]
]]
[[Returns][`*this`]]
]
``class_& staticmethod(char const* name);``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html 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:]]
]
``setattr(self, name, staticmethod(getattr(self, name)))``
[variablelist
[[Note][Attempting to invoke def(name,...) after invoking staticmethod(name) will [link raise] a RuntimeError.]]
[[Returns][`*this`]]
]
``
template <unspecified>
class_& def(detail::operator_<unspecified>);
``
[variablelist
[[Effects][Adds a Python [@http://www.python.org/doc/ref/specialnames.html special method] as described [link high_level_components.boost_python_operators_hpp here].]]
[[Returns][`*this`]]
]
``
template <class U>
class_& setattr(char const* name, U const& u);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].]]
[[Effects][Converts `u` to Python and adds it to the attribute dictionary of the extension class:
``PyObject_SetAttrString(this->ptr(), name, object(u).ptr());``]]
[[Returns][`*this`]]
]
``
template <class Get>
void add_property(char const* name, Get const& fget, char const* doc=0);
template <class Get, class Set>
void add_property(
char const* name, Get const& fget, Set const& fset, char const* doc=0);
``
[variablelist
[[Requires][name is an [link ntbs] which conform to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].]]
[[Effects][Creates a new Python [@http://www.python.org/2.2.2/descrintro.html#property 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);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].]]
[[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.]]
]
``
template <class D>
class_& def_readonly(char const* name, D T::*pm, char const* doc=0);
template <class D>
class_& def_readonly(char const* name, D const& d);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules]. `doc` is also an [link ntbs].]]
[[Effects][``this->add_property(name, make_getter(pm), doc);`` and ``this->add_static_property(name, make_getter(d));`` respectively.]]
[[Returns][`*this`]]
[[Rationale][Allows users to easily expose a class' data member or free variable such that it can be inspected from Python with a natural syntax.]]
]
``
template <class D>
class_& def_readwrite(char const* name, D T::*pm, char const* doc=0);
template <class D>
class_& def_readwrite(char const* name, D& d);
``
[variablelist
[[Effects][``this->add_property(name, make_getter(pm), make_setter(pm), doc);`` and ``this->add_static_property(name, make_getter(d), make_setter(d));`` respectively.]]
[[Returns][`*this`]]
[[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.]]
]
``
template <typename PickleSuite>
class_& def_pickle(PickleSuite const&);
``
[variablelist
[[Requires][PickleSuite must be publically derived from [link topics.pickle_support.the_pickle_interface 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 [link topics.pickle_support.the_pickle_interface easy to use high-level interface] for establishing complete [link topics.pickle_support.the_pickle_interface pickle support] for the wrapped class. The user is protected by compile-time consistency checks.]]
]
``class_& enable_pickling();``
[variablelist
[[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.]]
]
[endsect]
[endsect]
[section Class template bases<T1, T2, ...TN>]
An MPL sequence which can be used in class_<...> instantiations indicate a list of base classes.
[section Class template bases synopsis]
``
namespace boost { namespace python
{
template <T1 = unspecified,...Tn = unspecified>
struct bases
{};
}}
``
[endsect]
[endsect]
[section Examples]
Given a C++ class declaration:
``
class Foo : public Bar, public Baz
{
public:
Foo(int x, char const* y);
Foo(double);
std::string const& name() { return m_name; }
void name(char const*);
double value; // public data
private:
...
};
``
A corresponding Boost.Python extension class can be created with:
``
using namespace boost::python;
class_<Foo,bases<Bar,Baz> >("Foo",
"This is Foo's docstring."
"It describes our Foo extension class",
init<int,char const*>(args("x","y"), "__init__ docstring")
)
.def(init<double>())
.def("get_name", &Foo::get_name, return_internal_reference<>())
.def("set_name", &Foo::set_name)
.def_readwrite("value", &Foo::value);
``
[endsect]
[endsect]

View File

@@ -1,18 +0,0 @@
[chapter High Level Components
[quickbook 1.7]
]
[include class.qbk]
[include def.qbk]
[include def_visitor.qbk]
[include docstring_options.qbk]
[include enum.qbk]
[include errors.qbk]
[include exception_translator.qbk]
[include init.qbk]
[include iterator.qbk]
[include module.qbk]
[include operators.qbk]
[include scope.qbk]
[include stl_iterator.qbk]
[include wrapper.qbk]

View File

@@ -1,134 +0,0 @@
[chapter Concepts
[quickbook 1.7]
]
[section CallPolicies]
[section Introduction]
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
[endsect]
[section 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`.
[endsect]
[section Concept Requirements]
[table
[[Expression][Type][Result/Semantics]]
[[`x.precall(a)`][convertible to `bool`]
[returns `false` and `PyErr_Occurred() != 0` upon failure, `true` otherwise.]]
[[`P::result_converter`][A model of `ResultConverterGenerator`.]
[An MPL unary Metafunction Class used produce the "preliminary" result object.]]
[[`x.postcall(a, r)`][convertible to `PyObject*`]
[`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.]]
[[`P::extract_return_type`][A model of Metafunction.]
[An MPL unary Metafunction used extract the return type from a given signature. By default it is derived from `mpl::front`.]]
]
[endsect]
[endsect]
[section Dereferenceable]
[section Introduction]
Instances of a `Dereferenceable` type can be used like a pointer to access an lvalue.
[endsect]
[section Concept Requirements]
In the table below, `T` is a model of Dereferenceable, and `x` denotes an object of type `T`. In addition, all pointers are `Dereferenceable`.
[table
[[Expression][Result][Operational Semantics]]
[[`get_pointer(x)`][convertible to `pointee<T>::type*`]
[`&*x`, or a null pointer ]]
]
[endsect]
[endsect]
[section Extractor]
[section Introduction]
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.
[endsect]
[section Concept Requirements]
In the table below, `X` denotes a model of `Extractor` and `a` denotes an instance of a Python object type.
[table
[[Expression][Type][Semantics]]
[[`X::execute(a)`][non-void]
[Returns the C++ object being extracted. The execute function must not be overloaded.]]
[[`&a.ob_type`][`PyTypeObject**`]
[Points to the `ob_type` field of an object which is layout-compatible with `PyObject`]]
]
[endsect]
[section 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.
[endsect]
[endsect]
[section HolderGenerator]
[section Introduction]
A HolderGenerator is a unary metafunction class which returns types suitable for holding instances of its argument in a wrapped C++ class instance.
[endsect]
[section Concept Requirements]
In the table below, `G` denotes an type which models `HolderGenerator`, and `X` denotes a class type.
[table
[[Expression][Requirements]]
[[`G::apply<X>::type`][A concrete subclass of `instance_holder` which can hold objects of type `X`. ]]
]
[endsect]
[endsect]
[section ResultConverter]
[section Introduction]
A ResultConverter for a type `T` is a type whose instances can be used to convert C++ return values of type `T` `to_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.
[endsect]
[section ResultConverter Concept Requirements]
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`.
[table
[[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.]]
]
[endsect]
[section ResultConverterGenerator Concept Requirements]
In the table below, `G` denotes a ResultConverterGenerator type and `R` denotes a possible C++ function return type.
[table
[[Expression][Requirements]]
[[`G::apply<R>::type`][A ResultConverter type for `R`.]]
]
[endsect]
[endsect]
[section ObjectWrapper]
[section Introduction]
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.
[endsect]
[section ObjectWrapper Concept Requirements]
Models of the ObjectWrapper concept have [link object_wrappers.boost_python_object_hpp.class_object 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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper], a member function invocation of the form ``x.some_function(a1, a2,...an)`` always has semantics equivalent to:
``extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()`` (see [link concepts.objectwrapper.caveat caveat] below).
[endsect]
[section TypeWrapper Concept Requirements]
TypeWrapper is a refinement of [link concepts.objectwrapper.objectwrapper_concept_requiremen 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 ``object(a1), object(a2),...object(an)``.
When used as arguments to wrapped C++ functions, or as the template parameter to [link to_from_python_type_conversion.boost_python_extract_hpp.class_template_extract extract<>], only instances of the associated Python type will be considered a match.
[endsect]
[section Caveat]
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 [link object_wrappers.boost_python_dict_hpp.class_dict dict] member function `items` returns an object of type [link object_wrappers.boost_python_list_hpp.class_list 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, [link object_wrappers.boost_python_dict_hpp.class_dict boost::python::dict] can accept objects of Python type `mydict`. Invoking `items()` on this object can result in an instance of [link object_wrappers.boost_python_list_hpp.class_list 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.
[endsect]
[endsect]

View File

@@ -1,10 +0,0 @@
[chapter To/From Python Type Conversion
[quickbook 1.7]
]
[include extract.qbk]
[include implicit.qbk]
[include lvalue_from_pytype.qbk]
[include opaque_pointer_converter.qbk]
[include to_python_converter.qbk]
[include register_ptr_to_python.qbk]

View File

@@ -1,58 +0,0 @@
[section boost/python/copy_const_reference.hpp]
[section Class `copy_const_reference`]
`copy_const_reference` is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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.
``
namespace boost { namespace python
{
struct copy_const_reference
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `copy_const_reference` metafunctions]
``template <class T> struct apply``
[variablelist
[[Requires][`T` is `U const&` for some `U`.]]
[[Returns][`typedef to_python_value<T> type;`]]
]
[endsect]
[section Example]
C++ module definition:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>
// classes to wrap
struct Bar { int x; }
struct Foo {
Foo(int x) : { b.x = x; }
Bar const& get_bar() const { return b; }
private:
Bar b;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
class_<Bar>("Bar");
class_<Foo>("Foo", init<int>())
.def("get_bar", &Foo::get_bar
, return_value_policy<copy_const_reference>())
;
}
``
Python code:
``
>>> from my_module import *
>>> f = Foo(3) # create a Foo object
>>> b = f.get_bar() # make a copy of the internal Bar object
``
[endsect]
[endsect]

View File

@@ -1,58 +0,0 @@
[section boost/python/copy_non_const_reference.hpp]
[section Class `copy_non_const_reference`]
`copy_non_const_reference` is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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.
``
namespace boost { namespace python
{
struct copy_non_const_reference
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `copy_non_const_reference` metafunctions]
``template <class T> struct apply``
[variablelist
[[Requires][`T` is `U &` for some non-const `U`.]]
[[Returns][`typedef to_python_value<T> type`;]]
]
[endsect]
[section Example]
C++ module definition:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_non_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>
// classes to wrap
struct Bar { int x; }
struct Foo {
Foo(int x) : { b.x = x; }
Bar& get_bar() { return b; }
private:
Bar b;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
class_<Bar>("Bar");
class_<Foo>("Foo", init<int>())
.def("get_bar", &Foo::get_bar
, return_value_policy<copy_non_const_reference>())
;
}
``
Python code:
``
>>> from my_module import *
>>> f = Foo(3) # create a Foo object
>>> b = f.get_bar() # make a copy of the internal Bar object
``
[endsect]
[endsect]

View File

@@ -1,98 +0,0 @@
[section boost/python/data_members.hpp]
[section Introduction]
`make_getter()` and `make_setter()` are the functions used internally by [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu `class_<>::def_readonly`] and [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu `class_<>::def_readwrite`] to produce Python callable objects which wrap C++ data members.
[endsect]
[section 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);
``
[variablelist
[[Requires][Policies is a model of [link concepts.callpolicies `CallPolicies`].]]
[[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.]]
]
``
template <class D>
object make_getter(D const& d);
template <class D, class Policies>
object make_getter(D const& d, Policies const& policies);
template <class D>
object make_getter(D const* p);
template <class D, class Policies>
object make_getter(D const* p, Policies const& policies);
``
[variablelist
[[Requires][Policies is a model of CallPolicies.]]
[[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);
``
[variablelist
[[Requires][Policies is a model of CallPolicies.]]
[[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.]]
]
``
template <class D>
object make_setter(D& d);
template <class D, class Policies>
object make_setter(D& d, Policies const& policies);
template <class D>
object make_setter(D* p);
template <class D, class Policies>
object make_setter(D* p, Policies const& policies);
``
[variablelist
[[Requires][Policies is a model of CallPolicies.]]
[[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.]]
]
[endsect]
[section Example]
The code below uses make_getter and make_setter to expose a data member as functions:
``
#include <boost/python/data_members.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
struct X
{
X(int x) : y(x) {}
int y;
};
using namespace boost::python;
BOOST_PYTHON_MODULE_INIT(data_members_example)
{
class_<X>("X", init<int>())
.def("get", make_getter(&X::y))
.def("set", make_setter(&X::y))
;
}
``
It can be used this way in Python:
``
>>> from data_members_example import *
>>> x = X(1)
>>> x.get()
1
>>> x.set(2)
>>> x.get()
2
``
[endsect]
[endsect]

View File

@@ -1,54 +0,0 @@
[section boost/python/def.hpp]
[section Introduction]
`def()` is the function which can be used to expose C++ functions and callable objects as Python functions in the [link high_level_components.boost_python_scope_hpp.introduction current scope].
[endsect]
[section Functions]
``
template <class F>
void def(char const* name, F f);
template <class Fn, class A1>
void def(char const* name, Fn fn, A1 const&);
template <class Fn, class A1, class A2>
void def(char const* name, Fn fn, A1 const&, A2 const&);
template <class Fn, class A1, class A2, class A3>
void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].
* If `Fn` is [derived from] [link object_wrappers.boost_python_object_hpp.class_object object], it will be added to the [link high_level_components.boost_python_scope_hpp.introduction current scope] as a single overload. To be useful, `fn` should be [@http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-6 callable].
* If `a1` is the result of an [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions overload-dispatch-expression], only the second form is allowed and `fn` must be a pointer to function or pointer to member function whose [link arity] is the same as A1's [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions maximum arity].
[*Effects:] For each prefix `P` of `Fn`\ 's sequence of argument types, beginning with the one whose length is `A1`\ 's [link function_invocation_and_creation.boost_python_overloads_hpp.introduction.overload_dispatch_expressions minimum arity], adds a `name(...)` function overload to the [link high_level_components.boost_python_scope_hpp.introduction 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.
[table
[[Mnemonic Name][Requirements/Type properties][Effects]]
[[docstring][Any [link ntbs]][Value will be bound to the `__doc__` attribute of the resulting method overload.]]
[[policies][A model of [link concepts.callpolicies CallPolicies]][A copy will be used as the call policies of the resulting method overload.]]
[[keywords][The result of a [link function_invocation_and_creation.boost_python_args_hpp.introduction.keyword_expressions keyword-expression] specifying no more arguments than the [link arity] of `fn`.][A copy will be used as the call policies of the resulting method overload.]]
]
]]
]
[endsect]
[section Example]
``
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>
#include <boost/python/args.hpp>
using namespace boost::python;
char const* foo(int x, int y) { return "foo"; }
BOOST_PYTHON_MODULE(def_test)
{
def("foo", foo, args("x", "y"), "foo's docstring");
}
``
[endsect]
[endsect]

View File

@@ -1,58 +0,0 @@
[section boost/python/def_visitor.hpp]
[section Introduction]
<boost/python/def_visitor.hpp> provides a generic visitation interface through which the [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel class_] def member functionality can be extended non-intrusively to avoid cluttering the [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel 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.
[endsect]
[section Class `def_visitor`]
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 [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel class_] `def` member function.
``
namespace boost { namespace python {
template <class DerivedVisitor>
class def_visitor {};
}
``
[variablelist
[[Requires][The client supplied class DerivedVisitor template parameter is expected to:
* be privately derived from def_visitor
* grant friend access to class def_visitor_access
* define either or both visit member functions listed in the table below:
[table
[[Expression][Return Type][Requirements][Effects]]
[[`visitor.visit(cls)`][`void`]
[`cls` is an instance of a [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel class_] being wrapped to Python. `visitor` is a `def_visitor` derived class.]
[A call to `cls.def(visitor)` forwards to this member function.]]
[[`visitor.visit(cls, name, options)`][`void`]
[`cls` is a [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel class_] instance, name is a C string. `visitor` is a `def_visitor` derived class. options is a context specific optional argument.]
[A call to `cls.def(name, visitor)` or `cls.def(name, visitor, options)` forwards to this member function. ]]]
]]
]
[endsect]
[section Example]
``
class X {/*...*/};
class my_def_visitor : boost::python::def_visitor<my_def_visitor>
{
friend class def_visitor_access;
template <class classT>
void visit(classT& c) const
{
c.def("foo", &my_def_visitor::foo);
c.def("bar", &my_def_visitor::bar);
}
static void foo(X& self);
static void bar(X& self);
};
BOOST_PYTHON_MODULE(my_ext)
{
class_<X>("X")
.def(my_def_visitor());
}
``
[endsect]
[endsect]

View File

@@ -1,58 +0,0 @@
[section boost/python/default_call_policies.hpp]
[section Class `default_call_policies`]
`default_call_policies` is a model of [link concepts.callpolicies `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 [link concepts.callpolicies `CallPolicies`] from `default_call_policies`.
``
namespace boost { namespace python
{
struct default_call_policies
{
static bool precall(PyObject*);
static PyObject* postcall(PyObject*, PyObject* result);
typedef default_result_converter result_converter;
template <class Sig> struct extract_return_type : mpl::front<Sig>{};
};
}}
``
[endsect]
[section Class `default_call_policies` static functions]
``bool precall(PyObject*);``
[variablelist
[[Returns][true]]
[[Throws][nothing]]
]
``PyObject* postcall(PyObject*, PyObject* result);``
[variablelist
[[Returns][result]]
[[Throws][nothing]]
]
[endsect]
[section Class `default_result_converter`]
default_result_converter is a model of [link concepts.resultconverter.resultconvertergenerator_concept `ResultConverterGenerator`] which can be used to wrap C++ functions returning non-pointer types, `char const*`, and `PyObject*`, by-value.
``
namespace boost { namespace python
{
struct default_result_converter
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `default_result_converter` metafunctions]
``template <class T> struct apply``
[variablelist
[[Requires][T is not a reference type. If T is a pointer type, T is const char* or PyObject*. ]]
[[Returns][typedef to_python_value<T const&> type;]]
]
[endsect]
[section Example]
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;
};
``
[endsect]
[endsect]

View File

@@ -1,71 +0,0 @@
[section boost/python/dict.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/dev/doc/devel/lib/typesmapping.html `dict`] type.
[endsect]
[section Class `dict`]
Exposes the [@http://www.python.org/dev/doc/devel/lib/typesmapping.html 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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since `dict` is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `dict` instances as well.
``
namespace boost { namespace python
{
class dict : public object
{
dict();
template< class T >
dict(T const & data);
// modifiers
void clear();
dict copy();
template <class T1, class T2>
tuple popitem();
template <class T>
object setdefault(T const &k);
template <class T1, class T2>
object setdefault(T1 const & k, T2 const & d);
void update(object_cref E);
template< class T >
void update(T const & E);
// observers
list values() const;
object get(object_cref k) const;
template<class T>
object get(T const & k) const;
object get(object_cref k, object_cref d) const;
object get(T1 const & k, T2 const & d) const;
bool has_key(object_cref k) const;
template< class T >
bool has_key(T const & k) const;
list items() const;
object iteritems() const;
object iterkeys() const;
object itervalues() const;
list keys() const;
};
}}
``
[endsect]
[section Example]
``
using namespace boost::python;
dict swap_object_dict(object target, dict d)
{
dict result = extract<dict>(target.attr("__dict__"));
target.attr("__dict__") = d;
return result;
}
``
[endsect]
[endsect]

View File

@@ -1,213 +0,0 @@
[section boost/python/docstring_options.hpp]
[section Introduction]
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.
[endsect]
[section 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.
``namespace boost { namespace python {
class docstring_options : boost::noncopyable
{
public:
docstring_options(bool show_all=true);
docstring_options(bool show_user_defined, bool show_signatures);
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
~docstring_options();
void disable_user_defined();
void enable_user_defined();
void disable_signatures();
void enable_signatures();
void disable_py_signatures();
void enable_py_signatures();
void disable_cpp_signatures();
void enable_cpp_signatures();
void disable_all();
void enable_all();
};
}}
``
[endsect]
[section Class dostring_options constructors]
``
docstring_options(bool show_all=true);
``
[variablelist
[[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`.]]
]
``
docstring_options(bool show_user_defined, bool show_signatures);
``
[variablelist
[[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`.]]
]
``
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
``
[variablelist
[[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`.]]
]
[endsect]
[section Class docstring_options destructor]
``~docstring_options();``
[variablelist
[[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.]]]
[endsect]
[section Class `docstring_options` modifier functions]
``
void disable_user_defined();
void enable_user_defined();
void disable_signatures();
void enable_signatures();
void disable_py_signatures();
void enable_py_signatures();
void disable_cpp_signatures();
void enable_cpp_signatures();
void disable_all();
void enable_all();
``
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.
[endsect]
[section Example]
[section Docstring options defined at compile time]
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/docstring_options.hpp>
void foo() {}
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options(DEMO_DOCSTRING_SHOW_ALL);
def("foo", foo, "foo doc");
}
``
If compiled with `-DDEMO_DOCSTRING_SHOW_ALL=true`:
``
>>> import demo
>>> print demo.foo.__doc__
foo() -> None : foo doc
C++ signature:
foo(void) -> void
``
If compiled with `-DDEMO_DOCSTRING_SHOW_ALL=false`:
``
>>> import demo
>>> print demo.foo.__doc__
None
``
[endsect]
[section Selective suppressions]
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/docstring_options.hpp>
int foo1(int i) { return i; }
int foo2(long l) { return static_cast<int>(l); }
int foo3(float f) { return static_cast<int>(f); }
int foo4(double d) { return static_cast<int>(d); }
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options;
def("foo1", foo1, arg("i"), "foo1 doc");
doc_options.disable_user_defined();
def("foo2", foo2, arg("l"), "foo2 doc");
doc_options.disable_signatures();
def("foo3", foo3, arg("f"), "foo3 doc");
doc_options.enable_user_defined();
def("foo4", foo4, arg("d"), "foo4 doc");
doc_options.enable_py_signatures();
def("foo5", foo4, arg("d"), "foo5 doc");
doc_options.disable_py_signatures();
doc_options.enable_cpp_signatures();
def("foo6", foo4, arg("d"), "foo6 doc");
}
``
Python code:
``
>>> import demo
>>> print demo.foo1.__doc__
foo1( (int)i) -> int : foo1 doc
C++ signature:
foo1(int i) -> int
>>> print demo.foo2.__doc__
foo2( (int)l) -> int :
C++ signature:
foo2(long l) -> int
>>> print demo.foo3.__doc__
None
>>> print demo.foo4.__doc__
foo4 doc
>>> print demo.foo5.__doc__
foo5( (float)d) -> int : foo5 doc
>>> print demo.foo6.__doc__
foo6 doc
C++ signature:
foo6(double d) -> int
``
[endsect]
[section Wrapping from multiple C++ scopes]
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/docstring_options.hpp>
int foo1(int i) { return i; }
int foo2(long l) { return static_cast<int>(l); }
int bar1(int i) { return i; }
int bar2(long l) { return static_cast<int>(l); }
namespace {
void wrap_foos()
{
using namespace boost::python;
// no docstring_options here
// -> settings from outer C++ scope are in effect
def("foo1", foo1, arg("i"), "foo1 doc");
def("foo2", foo2, arg("l"), "foo2 doc");
}
void wrap_bars()
{
using namespace boost::python;
bool show_user_defined = true;
bool show_signatures = false;
docstring_options doc_options(show_user_defined, show_signatures);
def("bar1", bar1, arg("i"), "bar1 doc");
def("bar2", bar2, arg("l"), "bar2 doc");
}
}
BOOST_PYTHON_MODULE(demo)
{
boost::python::docstring_options doc_options(false);
wrap_foos();
wrap_bars();
}
``
Python code:
``
>>> import demo
>>> print demo.foo1.__doc__
None
>>> print demo.foo2.__doc__
None
>>> print demo.bar1.__doc__
bar1 doc
>>> print demo.bar2.__doc__
bar2 doc
``
[endsect]
[endsect]
[endsect]

View File

@@ -1,6 +0,0 @@
[chapter Embedding
[quickbook 1.7]
]
[include exec.qbk]
[include import.qbk]

View File

@@ -1,107 +0,0 @@
[section boost/python/enum.hpp]
[section Introduction]
<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.
[endsect]
[section Class template `enum_`]
Creates a Python class derived from Python's `int` type which is associated with the C++ type passed as its first parameter.
``
namespace boost { namespace python
{
template <class T>
class enum_ : public object
{
enum_(char const* name, char const* doc = 0);
enum_<T>& value(char const* name, T);
enum_<T>& export_values();
};
}}
``
[endsect]
[section Class template `enum_` constructors]
``enum_(char const* name, char const* doc=0);``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].]]
[[Effects][Constructs an `enum_` object holding a Python extension type derived from `int` which is named `name`. The named attribute of the [link high_level_components.boost_python_scope_hpp current scope] is bound to the new extension type.]]
]
[endsect]
[section Class template `enum_` modifier functions]
``enum_<T>& value(char const* name, T x);``
[variablelist
[[Requires][name is an [link ntbs] which conforms to Python's [@http://www.python.org/doc/current/ref/identifiers.html identifier naming rules].]]
[[Effects][adds an instance of the wrapped enumeration type with value x to the type's dictionary as the named attribute.]]
[[Returns][`*this`]]
]
``enum_<T>& export_values();``
[variablelist
[[Effects][sets attributes in the [link high_level_components.boost_python_scope_hpp current scope] with the same names and values as all enumeration values exposed so far by calling value().]]
[[Returns][`*this`]]
]
[endsect]
[section Example]
C++ module definition
``
#include <boost/python/enum.hpp>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>
using namespace boost::python;
enum color { red = 1, green = 2, blue = 4 };
color identity_(color x) { return x; }
BOOST_PYTHON_MODULE(enums)
{
enum_<color>("color")
.value("red", red)
.value("green", green)
.export_values()
.value("blue", blue)
;
def("identity", identity_);
}
``
Interactive Python:
``
>>> from enums import *
>>> identity(red)
enums.color.red
>>> identity(color.red)
enums.color.red
>>> identity(green)
enums.color.green
>>> identity(color.green)
enums.color.green
>>> identity(blue)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'blue' is not defined
>>> identity(color.blue)
enums.color.blue
>>> identity(color(1))
enums.color.red
>>> identity(color(2))
enums.color.green
>>> identity(color(3))
enums.color(3)
>>> identity(color(4))
enums.color.blue
>>> identity(1)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: bad argument type for built-in operation
``
[endsect]
[endsect]

View File

@@ -1,142 +0,0 @@
[section boost/python/errors.hpp]
[section Introduction]
<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.
[endsect]
[section 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 [@http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71 PyErr_Occurred()] returns a value convertible to `true`. Portable code shouldn't throw this exception type directly, but should instead use [link high_level_components.boost_python_errors_hpp.functions throw_error_already_set()], below.
``
namespace boost { namespace python
{
class error_already_set {};
}}
``
[endsect]
[section Functions]
``
template <class T> bool handle_exception(T f) throw();
void handle_exception() throw();
``
[variablelist
[[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 [link high_level_components.boost_python_exception_translato 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: [link function_invocation_and_creation.boost_python_make_function_hpp.functions make_function()], [link function_invocation_and_creation.boost_python_make_function_hpp.functions make_constructor()], [link high_level_components.boost_python_def_hpp.functions def()] and [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu 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.]]
]
``template <class T> T* expect_non_null(T* x);``
[variablelist
[[Returns][x]]
[[Throws][error_already_set() iff x == 0.]]
[[Rationale][Simplifies error-handling when calling functions in the Python/C API which return 0 on error.]]
]
``void throw_error_already_set();``
[variablelist
[[Effects][throw error_already_set();]]
[[Rationale][Simplifies error-handling when calling functions in the Python/C API which return 0 on error.]]
]
``void throw_error_already_set();``
[variablelist
[[Effects][throw error_already_set();]]
[[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.]]
]
[endsect]
[section Example]
``
#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;
}
}
``
[endsect]
[endsect]

View File

@@ -1,51 +0,0 @@
[section boost/python/exception_translator.hpp]
[section Introduction]
As described [link high_level_components.boost_python_errors_hpp.introduction 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 [@http://www.python.org/doc/current/lib/module-exceptions.html RuntimeError] exception whose representation is 'Unidentifiable C++ Exception'. To produce better error messages, users can register additional exception translators as described below.
[endsect]
[section Function `register_exception_translator`]
``
template<class ExceptionType, class Translate>
void register_exception_translator(Translate translate);
``
[variablelist
[[Requires][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).]]
]
[endsect]
[section 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);
}
``
[endsect]
[endsect]

View File

@@ -1,84 +0,0 @@
[section boost/python/exec.hpp]
[section Introduction]
Exposes a mechanism for embedding the python interpreter into C++ code.
[endsect]
[section Function `eval`]
``
object eval(str expression,
object globals = object(),
object locals = object());
``
[variablelist
[[Effects][Evaluate Python expression from expression in the context specified by the dictionaries globals and locals. ]]
[[Returns][An instance of object which holds the value of the expression.]]
]
[endsect]
[section Function `exec`]
``
object exec(str code,
object globals = object(),
object locals = object());
``
[variablelist
[[Effects][Execute Python source code from code in the context specified by the dictionaries globals and locals. ]]
[[Returns][ An instance of object which holds the result of executing the code. ]]
]
[endsect]
[section Function `exec_file`]
``
object exec_file(str filename,
object globals = object(),
object locals = object());
``
[variablelist
[[Effects][Execute Python source code from the file named by filename in the context specified by the dictionaries globals and locals.]]
[[Returns][An instance of object which holds the result of executing the code. ]]
]
[endsect]
[section Examples]
The following example demonstrates the use of import and exec to define a function in python, and later call it from within C++.
``
#include <iostream>
#include <string>
using namespace boost::python;
void greet()
{
// Retrieve the main module.
object main = import("__main__");
// Retrieve the main module's namespace
object global(main.attr("__dict__"));
// Define greet function in Python.
object result = exec(
"def greet(): \n"
" return 'Hello from Python!' \n",
global, global);
// Create a reference to it.
object greet = global["greet"];
// Call it.
std::string message = extract<std::string>(greet());
std::cout << message << std::endl;
}
``
Instead of embedding the python script into a string, we could also store it in an a file...
``
def greet():
return 'Hello from Python!'
``
... and execute that instead.
``
// ...
// Load the greet function from a file.
object result = exec_file(script, global, global);
// ...
}
``
[endsect]
[endsect]

View File

@@ -1,99 +0,0 @@
[section boost/python/extract.hpp]
[section Introduction]
Exposes a mechanism for extracting C++ object values from generalized Python objects. Note that `extract<...>` can also be used to "downcast" an [link object_wrappers.boost_python_object_hpp.class_object `object`] to some specific [link concepts.objectwrapper 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 [link concepts.objectwrapper ObjectWrapper]\ 's interface on the original object.
[endsect]
[section Class template `extract`]
`extract<T>` can be used to extract a value of an arbitrary C++ type from an instance of [link object_wrappers.boost_python_object_hpp.class_object 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.
``
namespace boost { namespace python
{
template <class T>
struct extract
{
typedef unspecified result_type;
extract(PyObject*);
extract(object const&);
result_type operator()() const;
operator result_type() const;
bool check() const;
};
}}
``
[endsect]
[section Class template `extract` constructors and destructor]
``
extract(PyObject* p);
extract(object const&);
``
[variablelist
[[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.]]
]
[endsect]
[section Class template `extract` observer functions]
``
result_type operator()() const;
operator result_type() const;
``
[variablelist
[[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][[link high_level_components.boost_python_errors_hpp.class_error_already_set `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;``
[variablelist
[[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][false only if no conversion from the stored pointer to T is available.]]
]
[endsect]
[section Example]
``
#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 [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel `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);
}
``
[endsect]
[endsect]

View File

@@ -1,129 +0,0 @@
[section boost/python/function_doc_signature.hpp]
[section Introduction]
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.
[endsect]
[section Class `function_doc_signature_generator`]
The class has only one public function which returns a list of strings documenting the overloads of a function.
``
namespace boost { namespace python { namespace objects {
class function_doc_signature_generator
{
public:
static list function_doc_signatures(function const *f);
};
}}}
``
[endsect]
[section Example]
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/class.hpp>
#include <boost/python/overloads.hpp>
#include <boost/python/raw_function.hpp>
using namespace boost::python;
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
{
return make_tuple(x, y, z);
}
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
struct X
{
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
{
return make_tuple(x, y, z);
}
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
tuple raw_func(tuple args, dict kw)
{
return make_tuple(args, kw);
}
BOOST_PYTHON_MODULE(args_ext)
{
def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
, "This is f's docstring"
);
def("raw", raw_function(raw_func));
def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
class_<X>("X", "This is X's docstring", init<>(args("self")))
.def("f", &X::f
, "This is X.f's docstring"
, args("self","x", "y", "z"))
;
}
``
Python code: [python]
``
>>> import args_ext
>>> help(args_ext)
Help on module args_ext:
NAME
args_ext
FILE
args_ext.pyd
CLASSES
Boost.Python.instance(__builtin__.object)
X
class X(Boost.Python.instance)
| This is X's docstring
|
| Method resolution order:
| X
| Boost.Python.instance
| __builtin__.object
|
| Methods defined here:
|
| __init__(...)
| __init__( (object)self) -> None :
| C++ signature:
| void __init__(struct _object *)
|
| f(...)
| f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring
| C++ signature:
| class boost::python::tuple f(struct X {lvalue},int,double,char const *)
|
| .................
|
FUNCTIONS
f(...)
f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring
C++ signature:
class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]])
f1(...)
f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring
C++ signature:
class boost::python::tuple f1([ int [,double [,char const *]]])
raw(...)
object raw(tuple args, dict kwds) :
C++ signature:
object raw(tuple args, dict kwds)
``
[endsect]
[endsect]

View File

@@ -1,35 +0,0 @@
[chapter Function Invocation and Creation
[quickbook 1.7]
]
[include args.qbk]
[include call.qbk]
[include call_method.qbk]
[include data_members.qbk]
[include make_function.qbk]
[include overloads.qbk]
[include ptr.qbk]
[include raw_function.qbk]
[section Function documentation]
[include function_doc_signature.qbk]
[include pytype_function.qbk]
[endsect]
[section Models of CallPolicies]
[include default_call_policies.qbk]
[include return_arg.qbk]
[include return_internal_reference.qbk]
[include return_value_policy.qbk]
[include with_custodian_and_ward.qbk]
[endsect]
[section Models of ResultConverter]
[include to_python_indirect.qbk]
[include to_python_value.qbk]
[endsect]
[section Models of ResultConverterGenerator]
[include copy_const_reference.qbk]
[include copy_non_const_reference.qbk]
[include manage_new_object.qbk]
[include reference_existing_object.qbk]
[include return_by_value.qbk]
[include return_opaque_pointer.qbk]
[endsect]

View File

@@ -1,190 +0,0 @@
[section boost/python/handle.hpp]
[section Introduction]
<boost/python/handle.hpp> provides class template `handle`, a smart pointer for managing reference-counted Python objects.
[endsect]
[section 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 [link pod 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`.
``
namespace boost { namespace python
{
template <class T>
class handle
{
typedef unspecified-member-function-pointer bool_type;
public: // types
typedef T element_type;
public: // member functions
~handle();
template <class Y>
explicit handle(detail::borrowed<null_ok<Y> >* p);
template <class Y>
explicit handle(null_ok<detail::borrowed<Y> >* p);
template <class Y>
explicit handle(detail::borrowed<Y>* p);
template <class Y>
explicit handle(null_ok<Y>* p);
template <class Y>
explicit handle(Y* p);
handle();
handle& operator=(handle const& r);
template<typename Y>
handle& operator=(handle<Y> const & r); // never throws
template <typename Y>
handle(handle<Y> const& r);
handle(handle const& r);
T* operator-> () const;
T& operator* () const;
T* get() const;
void reset();
T* release();
operator bool_type() const; // never throws
private:
T* m_p;
};
template <class T> struct null_ok;
namespace detail { template <class T> struct borrowed; }
}}
``
[section Class template `handle` constructors and destructor]
``virtual ~handle();``
[variablelist
[[Effects][`Py_XDECREF(upcast<PyObject*>(m_p))`]]
]
``template <class Y>
explicit handle(detail::borrowed<null_ok<Y> >* p);
``
[variablelist
[[Effects][
``Py_XINCREF(upcast<PyObject*>(p));
m_p = upcast<T*>(p);
``
]]
]
``template <class Y>
explicit handle(null_ok<detail::borrowed<Y> >* p);``
[variablelist
[[Effects][
``Py_XINCREF(upcast<PyObject*>(p));
m_p = upcast<T*>(p);
``
]]
]
``template <class Y>
explicit handle(detail::borrowed<Y>* p);``
[variablelist
[[Effects][
``Py_XINCREF(upcast<PyObject*>(p));
m_p = upcast<T*>(expect_non_null(p));
``
]]
]
``template <class Y>
explicit handle(null_ok<Y>* p);
``
[variablelist
[[Effects][`m_p = upcast<T*>(p);`]]
]
``
template <class Y>
explicit handle(Y* p);
``
[variablelist
[[Effects][`m_p = upcast<T*>(expect_non_null(p));`]]
]
``
handle();
``
[variablelist
[[Effects][`m_p = 0;`]]
]
``
template <typename Y>
handle(handle<Y> const& r);
handle(handle const& r);
``
[variablelist
[[Effects][m_p = r.m_p; Py_XINCREF(upcast<PyObject*>(m_p));]]
]
[endsect]
[section Class template `handle` modifiers]
``
handle& operator=(handle const& r);
template<typename Y>
handle& operator=(handle<Y> const & r); // never throws
``
[variablelist
[[Effects][`Py_XINCREF(upcast<PyObject*>(r.m_p)); Py_XDECREF( upcast<PyObject*>(m_p)); m_p = r.m_p;`]]
]
``
T* release();
``
[variablelist
[[Effects][`T* x = m_p; m_p = 0; return x;`]]
]
``
void reset();
``
[variablelist
[[Effects][`*this = handle<T>();`]]
]
[endsect]
[section Class template `handle` observers]
``
T* operator-> () const;
T* get() const;
``
[variablelist
[[Returns][`m_p;`]]
]
``
T& operator* () const;
``
[variablelist
[[Returns][`*m_p;`]]
]
``
operator bool_type() const; // never throws
``
[variablelist
[[Returns][`0` if `m_p == 0`, a pointer convertible to true otherwise.]]
]
[endsect]
[endsect]
[section Function `borrowed`]
``
template <class T>
detail::borrowed<T>* borrowed(T* p)
{
return (detail::borrowed<T>*)p;
}
``
[endsect]
[section Function `allow_null`]
``
template <class T>
null_ok<T>* allow_null(T* p)
{
return (null_ok<T>*)p;
}
``
[endsect]
[endsect]

View File

@@ -1,115 +0,0 @@
[section boost/python/has_back_reference.hpp]
[section Introduction]
<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.
[endsect]
[section Class template `has_back_reference`]
A unary metafunction whose value is true iff its argument is a `pointer_wrapper<>`.
``
namespace boost { namespace python
{
template<class WrappedClass> class has_back_reference
{
typedef mpl::false_ type;
};
}}
``
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_`.
[endsect]
[section Examples]
In C++:
``
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/has_back_reference.hpp>
#include <boost/python/handle.hpp>
#include <boost/shared_ptr.hpp>
using namespace boost::python;
using boost::shared_ptr;
struct X
{
X(PyObject* self) : m_self(self), m_x(0) {}
X(PyObject* self, int x) : m_self(self), m_x(x) {}
X(PyObject* self, X const& other) : m_self(self), m_x(other.m_x) {}
handle<> self() { return handle<>(borrowed(m_self)); }
int get() { return m_x; }
void set(int x) { m_x = x; }
PyObject* m_self;
int m_x;
};
// specialize has_back_reference for X
namespace boost { namespace python
{
template <>
struct has_back_reference<X>
: mpl::true_
{};
}}
struct Y
{
Y() : m_x(0) {}
Y(int x) : m_x(x) {}
int get() { return m_x; }
void set(int x) { m_x = x; }
int m_x;
};
shared_ptr<Y>
Y_self(shared_ptr<Y> self) { return self; }
BOOST_PYTHON_MODULE(back_references)
{
class_<X>("X")
.def(init<int>())
.def("self", &X::self)
.def("get", &X::get)
.def("set", &X::set)
;
class_<Y, shared_ptr<Y> >("Y")
.def(init<int>())
.def("get", &Y::get)
.def("set", &Y::set)
.def("self", Y_self)
;
}
``
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.
In Python:
``
>>> 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)
``
[endsect]
[endsect]

View File

@@ -1,69 +0,0 @@
[section boost/python/implicit.hpp]
[section Introduction]
`implicitly_convertible` allows Boost.Python to implicitly take advantage of a C++ implicit or explicit conversion when matching Python objects to C++ argument types.
[endsect]
[section Function template `implicit_convertible`]
``
template <class Source, class Target>
void implicitly_convertible();
``
[table
[[Parameter][Description]]
[[Source][The source type of the implicit conversion]]
[[Target][The target type of the implicit conversion]]
]
[variablelist
[[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++.]]
]
[endsect]
[section Example]
In C++:
``
#include <boost/python/class.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/module.hpp>
using namespace boost::python;
struct X
{
X(int x) : v(x) {}
operator int() const { return v; }
int v;
};
int x_value(X const& x)
{
return x.v;
}
X make_x(int n) { return X(n); }
BOOST_PYTHON_MODULE(implicit_ext)
{
def("x_value", x_value);
def("make_x", make_x);
class_<X>("X",
init<int>())
;
implicitly_convertible<X,int>();
implicitly_convertible<int,X>();
}
``
In Python:
``
>>> from implicit_ext import *
>>> x_value(X(42))
42
>>> x_value(42)
42
>>> x = make_x(X(42))
>>> x_value(x)
42
``
[endsect]
[endsect]

View File

@@ -1,31 +0,0 @@
[section boost/python/import.hpp]
[section Introduction]
Exposes a mechanism for importing python modules.
[endsect]
[section Function `import`]
``object import(str name);``
[variablelist
[[Effects][Imports the module named by name.]]
[[Returns][An instance of object which holds a reference to the imported module.]]
]
[endsect]
[section Examples]
The following example demonstrates the use of import to access a function in python, and later call it from within C++.
``
#include <iostream>
#include <string>
using namespace boost::python;
void print_python_version()
{
// Load the sys module.
object sys = import("sys");
// Extract the python version.
std::string version = extract<std::string>(sys.attr("version"));
std::cout << version << std::endl;
}
``
[endsect]
[endsect]

View File

@@ -1,271 +0,0 @@
[section Indexing support]
[section Introduction]
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, [@http://www.python.org/doc/current/ref/sequence-types.html 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).
* Support slice indexes.
* Accept Python container arguments (e.g. `lists`, `tuples`) wherever appropriate.
* Allow for extensibility through re-definable policy classes.
* Provide predefined support for the most common STL and STL-like indexable containers.
[endsect]
[section The Indexing Interface]
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):
[variablelist
[[__len__(self)]
[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.]]
[[__getitem__(self, key)]
[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.]]]
[[__setitem__(self, key, value)]
[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.]]
[[__delitem__(self, key)]
[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.]]
[[__iter__(self)]
[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 [@http://www.python.org/doc/current/lib/typeiter.html Iterator Types] in the [@http://www.python.org/doc/current/lib/lib.html Python Library Reference].]]
[[__contains__(self, item)]
[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.]]
]
[endsect]
[section index_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.
[section vector_index_suite]
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> >())
;
``
XVec is now a full-fledged Python container (see the example in full, along with its python test).
[endsect]
[section map_index_suite]
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).
[endsect]
[endsect]
[section `indexing_suite` class]
[table
[[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
}
``
[section DerivedPolicies]
Derived classes provide the hooks needed by the indexing_suite:
``
data_type&
get_item(Container& container, index_type i);
static object
get_slice(Container& container, index_type from, index_type to);
static void
set_item(Container& container, index_type i, data_type const& v);
static void
set_slice(
Container& container, index_type from,
index_type to, data_type const& v
);
template <class Iter>
static void
set_slice(Container& container, index_type from,
index_type to, Iter first, Iter last
);
static void
delete_item(Container& container, index_type i);
static void
delete_slice(Container& container, index_type from, index_type to);
static size_t
size(Container& container);
template <class T>
static bool
contains(Container& container, T const& val);
static index_type
convert_index(Container& container, PyObject* i);
static index_type
adjust_index(index_type current, index_type from,
index_type to, size_type len);
``
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.
[endsect]
[endsect]
[section class `vector_indexing_suite`]
[table
[[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:
typedef typename Container::value_type data_type;
typedef typename Container::value_type key_type;
typedef typename Container::size_type index_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
data_type&
get_item(Container& container, index_type i);
static object
get_slice(Container& container, index_type from, index_type to);
static void
set_item(Container& container, index_type i, data_type const& v);
static void
set_slice(Container& container, index_type from,
index_type to, data_type const& v);
template <class Iter>
static void
set_slice(Container& container, index_type from,
index_type to, Iter first, Iter last);
static void
delete_item(Container& container, index_type i);
static void
delete_slice(Container& container, index_type from, index_type to);
static size_t
size(Container& container);
static bool
contains(Container& container, key_type const& key);
static index_type
convert_index(Container& container, PyObject* i);
static index_type
adjust_index(index_type current, index_type from,
index_type to, size_type len);
};
``
[endsect]
[section class `map_indexing_suite`]
[table
[[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:
typedef typename Container::value_type value_type;
typedef typename Container::value_type::second_type data_type;
typedef typename Container::key_type key_type;
typedef typename Container::key_type index_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
static data_type&
get_item(Container& container, index_type i);
static void
set_item(Container& container, index_type i, data_type const& v);
static void
delete_item(Container& container, index_type i);
static size_t
size(Container& container);
static bool
contains(Container& container, key_type const& key);
static bool
compare_index(Container& container, index_type a, index_type b);
static index_type
convert_index(Container& container, PyObject* i);
};
``
[endsect]
[endsect]

View File

@@ -1,91 +0,0 @@
[section boost/python/init.hpp]
[section Introduction]
<boost/python/init.hpp> defines the interface for exposing C++ constructors to Python as extension class `__init__` functions.
[section init-expressions]
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:
[variablelist
[[docstring][An [link ntbs] whose value will bound to the method's `__doc__` attribute]]
[[keywords][A [link function_invocation_and_creation.boost_python_args_hpp.introduction.keyword_expressions 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 [link concepts.callpolicies 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.]]
]
[endsect]
[endsect]
[section Class template `init`]
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<...>.
``
namespace boost { namespace python
{
template <T1 = unspecified,...Tn = unspecified>
struct init
{
init(char const* doc = 0);
template <class Keywords> init(Keywords const& kw, char const* doc = 0);
template <class Keywords> init(char const* doc, Keywords const& kw);
template <class CallPolicies>
unspecified operator[](CallPolicies const& policies) const
};
}}
``
[section Class template `init` constructors]
``
init(char const* doc = 0);
template <class Keywords> init(Keywords const& kw, char const* doc = 0);
template <class Keywords> init(char const* doc, Keywords const& kw);
``
[variablelist
[[Requires][If supplied, doc is an [link 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 [link function_invocation_and_creation.models_of_callpolicies.boost_python_default_call_polici default_call_policies]. If Tn is [link high_level_components.boost_python_init_hpp.class_template_optional optional<U1, U2,... Um>], the expression's valid prefixes are given by: ``(T1, T2,...Tn-1), (T1, T2,...Tn-1 , U1), (T1, T2,...Tn-1 , U1, U2), ...(T1, T2,...Tn-1 , U1, U2,...Um)``.
Otherwise, the expression has one valid prefix given by the template arguments the user specified. ]]
]
[endsect]
[section Class template `init` observer functions]
``
template <class Policies>
unspecified operator[](Policies const& policies) const
``
[variablelist
[[Requires][Policies is a model of [link concepts.callpolicies CallPolicies].]]
[[Effects][Returns a new [link high_level_components.boost_python_init_hpp.introduction.init_expressions init-expression] with all the same properties as the init object except that its call policies are replaced by a reference to policies.]]
]
[endsect]
[endsect]
[section Class template `optional` ]
A MPL sequence which can be used to specify the optional arguments to an __init__ function.
``
namespace boost { namespace python
{
template <T1 = unspecified,...Tn = unspecified>
struct optional {};
}}
``
[endsect]
[section Example]
Given the C++ declarations:
``
class Y;
class X
{
public:
X(int x, Y* y) : m_y(y) {}
X(double);
private:
Y* m_y;
};
``
A corresponing Boost.Python extension class can be created with:
``
using namespace boost::python;
class_<X>("X", "This is X's docstring.",
init<int,char const*>(args("x","y"), "X.__init__'s docstring")[
with_custodian_and_ward<1,3>()]
)
.def(init<double>())
;
``
[endsect]
[endsect]

View File

@@ -1,92 +0,0 @@
[section boost/python/instance_holder.hpp]
[section Introduction]
<boost/python/instance_holder.hpp> provides class `instance_holder`, the base class for types which hold C++ instances of wrapped classes.
[endsect]
[section Class template `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.
``
namespace boost { namespace python
{
class instance_holder : noncopyable
{
public:
// destructor
virtual ~instance_holder();
// instance_holder modifiers
void install(PyObject* inst) throw();
// instance_holder observers
virtual void* holds(type_info) = 0;
};
}}
``
[section Class `intance_holder` destructor]
``virtual ~instance_holder();``
[variablelist
[[Effects][destroys the object]]
]
[endsect]
[section Class `intance_holder` modifiers]
``void install(PyObject* inst) throw();``
[variablelist
[[Requires][`inst` is a Python instance of a wrapped C++ class type, or is a type derived from a wrapped C++ class type. ]]
[[Effects][installs the new instance at the head of the Python object's chain of held instances. ]]
[[Throws][nothing]]
]
[endsect]
[section Class `intance_holder` observers]
``virtual void *holds(type_info x) = 0;``
[variablelist
[[Returns][A pointer to an object of the type described by `x` if `*this` contains such an object, 0 otherwise. ]]
]
[endsect]
[endsect]
[section Examples]
The following is a simplified version of the instance holder template used by Boost.Python to wrap classes held by smart pointers:
``
template <class SmartPtr, class Value>
struct pointer_holder : instance_holder
{
// construct from the SmartPtr type
pointer_holder(SmartPtr p)
:m_p(p)
// Forwarding constructors for the held type
pointer_holder(PyObject*)
:m_p(new Value())
{
}
template<class A0>
pointer_holder(PyObject*,A0 a0)
:m_p(new Value(a0))
{
}
template<class A0,class A1>
pointer_holder(PyObject*,A0 a0,A1 a1)
:m_p(new Value(a0,a1))
{
}
...
private: // required holder implementation
void* holds(type_info dst_t)
{
// holds an instance of the SmartPtr type...
if (dst_t == python::type_id<SmartPtr>())
return &this->m_p;
// ...and an instance of the SmartPtr's element_type, if the
// pointer is non-null
return python::type_id<Value>() == dst_t ? &*this->m_p : 0;
}
private: // data members
SmartPtr m_p;
};
``
[endsect]
[endsect]

View File

@@ -1,111 +0,0 @@
[section boost/python/iterator.hpp]
[section Introduction]
<boost/python/iterator.hpp> provides types and functions for creating [@http://www.python.org/doc/current/lib/typeiter.html Python iterators] from C++ Containers and Iterators. Note that if your `class_` supports random-access iterators, implementing [@http://www.python.org/doc/current/ref/sequence-types.html#l2h-128 __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 [@http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-35 `iter()`]), and each access can be range-checked, leaving no possiblity of accessing through an invalidated C++ iterator.
[endsect]
[section 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 [link concepts.callpolicies CallPolicies] `P` can be used to control how elements are returned during iteration.
In the table below, c is an instance of Container.
[table
[[Template Parameter][Requirements][Semantics][Default]]
[[Container][`[c.begin(),c.end()`) is a valid Iterator range.][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.][ ]]
[[NextPolicies][A default-constructible model of [link concepts.callpolicies CallPolicies].][Applied to the resulting iterators' `next()` method.][An unspecified model of [link concepts.callpolicies CallPolicies] which always makes a copy of the result of deferencing the underlying C++ iterator]]
]
``
namespace boost { namespace python
{
template <class Container, class NextPolicies = unspecified>
struct iterator : object
{
iterator();
};
}}
``
[endsect]
[section Class template iterator constructors]
``iterator()``
[variablelist
[[Effects][Initializes its base class with the result of:
``range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)``]]
[[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()`.]]
]
[endsect]
[section 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.
[table
[[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.]]
]
``
namespace boost { namespace python
{
template <class C>
struct iterators
{
typedef typename C::const_iterator iterator;
static iterator begin(C& x);
static iterator end(C& x);
};
}}
``
[endsect]
[section Class template iterators nested types]
If C is a const type,``typedef typename C::const_iterator iterator;``
Otherwise: ``typedef typename C::iterator iterator;``
[endsect]
[section Class template iterators static functions]
``static iterator begin(C&);``
[variablelist [[Returns][`x.begin()`]]]
``static iterator end(C&);``
[variablelist [[Returns][`x.end()`]]]
[endsect]
[section Functions]
``
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);
``
[variablelist
[[Requires][ NextPolicies is a default-constructible model of [link concepts.callpolicies 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 [link concepts.callpolicies 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 [link function_invocation_and_creation.models_of_callpolicies.boost_python_return_internal_ref.class_template_return_internal_r 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.]]
]
[endsect]
[section Example]
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <vector>
using namespace boost::python;
BOOST_PYTHON_MODULE(demo)
{
class_<std::vector<double> >("dvec")
.def("__iter__", iterator<std::vector<double> >())
;
}
``
[endsect]
[endsect]

View File

@@ -1,60 +0,0 @@
[section boost_python_list.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/doc/current/lib/typesseq-mutable.html list] type.
[endsect]
[section Class `list`]
Exposes the [@http://www.python.org/doc/current/lib/typesseq-mutable.html 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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since `list` is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `list` instances as well.``
namespace boost { namespace python
{
class list : public object
{
public:
list(); // new list
template <class T>
explicit list(T const& sequence);
template <class T>
void append(T const& x);
template <class T>
long count(T const& value) const;
template <class T>
void extend(T const& x);
template <class T>
long index(T const& x) const;
template <class T>
void insert(object const& index, T const& x); // insert object before index
object pop(); // remove and return item at index (default last)
object pop(long index);
object pop(object const& index);
template <class T>
void remove(T const& value);
void reverse(); // reverse *IN PLACE*
void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
template <class T>
void sort(T const& value);
};
}}
``
[endsect]
[section Example]
``
using namespace boost::python;
// Return the number of zeroes in the list
long zeroes(list l)
{
return l.count(0);
}
``
[endsect]
[endsect]

View File

@@ -1,38 +0,0 @@
[section boost/python/long.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/doc/current/lib/typesnumeric.html long] integer type.
[endsect]
[section Class `long_`]
Exposes the [@http://www.python.org/doc/current/lib/typesnumeric.html 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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since `long_` is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `long_` instances as well.
``
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);
};
}}
``
[endsect]
[section 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);
}
``
[endsect]
[endsect]

View File

@@ -1,120 +0,0 @@
[section boost/python/lvalue_from_pytype.hpp]
[section Introduction]
<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.
[endsect]
[section 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:
In the table below, x denotes an object of type PythonObject&
[table
[[Parameter][Requirements][Semantics]]
[[Extractor][a model of [link concepts.extractor `Extractor`] whose execute function returns a reference type.][Extracts the lvalue from the Python object once its type has been confirmed]]
[[python_type][A compile-time constant [@http://www.python.org/doc/2.2/ext/dnt-type-methods.html `PyTypeObject*`]][The Python type of instances convertible by this converter. Python subtypes are also convertible.]]
]
``
namespace boost { namespace python
{
template <class Extractor, PyTypeObject const* python_type>
struct lvalue_from_pytype
{
lvalue_from_pytype();
};
}}
``
[section Class template `lvalue_from_pytype` constructor]
``lvalue_from_pytype();``
[variablelist
[[Effects][Registers converters which can convert Python objects of the given type to lvalues of the type returned by Extractor::execute.]]
]
[endsect]
[endsect]
[section Class template `extract_identity`]
extract_identity is a model of [link concepts.extractor `Extractor`] which can be used in the common case where the C++ type to be extracted is the same as the Python object type.
``
namespace boost { namespace python
{
template <class InstanceType>
struct extract_identity
{
static InstanceType& execute(InstanceType& c);
};
}}
``
[section Class template `extract_identity` static functions]
``InstanceType& execute(InstanceType& c);``
[variablelist
[[Returns][c]]
]
[endsect]
[endsect]
[section Class template `extract_member`]
`extract_member` is a model of [link concepts.extractor `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.
``
namespace boost { namespace python
{
template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
struct extract_member
{
static MemberType& execute(InstanceType& c);
};
}}
``
[section Class template `extract_member` static functions]
``static MemberType& execute(InstanceType& c);``
[variablelist
[[Returns][`c.*member`]]
]
[endsect]
[endsect]
[section Example]
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.
In C++:
``
#include <boost/python/module.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/lvalue_from_pytype.hpp>
// definition lifted from the Python docs
typedef struct {
PyObject_HEAD
} noddy_NoddyObject;
using namespace boost::python;
static handle<noddy_NoddyObject> cache;
bool is_cached(noddy_NoddyObject* x)
{
return x == cache.get();
}
void set_cache(noddy_NoddyObject* x)
{
cache = handle<noddy_NoddyObject>(borrowed(x));
}
BOOST_PYTHON_MODULE(noddy_cache)
{
def("is_cached", is_cached);
def("set_cache", set_cache);
// register Noddy lvalue converter
lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
}
``
In Python:
``
>>> import noddy
>>> n = noddy.new_noddy()
>>> import noddy_cache
>>> noddy_cache.is_cached(n)
0
>>> noddy_cache.set_cache(n)
>>> noddy_cache.is_cached(n)
1
>>> noddy_cache.is_cached(noddy.new_noddy())
0
``
[endsect]
[endsect]

View File

@@ -1,83 +0,0 @@
[section boost/python/make_function.hpp]
[section Introduction]
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.
[endsect]
[section 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)
``
[variablelist
[[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)
``
[variablelist
[[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.]]
]
[endsect]
[section Example]
C++ function exposed below returns a callable object wrapping one of two functions.
``
#include <boost/python/make_function.hpp>
#include <boost/python/module.hpp>
char const* foo() { return "foo"; }
char const* bar() { return "bar"; }
using namespace boost::python;
object choose_function(bool selector)
{
if (selector)
return boost::python::make_function(foo);
else
return boost::python::make_function(bar);
}
BOOST_PYTHON_MODULE(make_function_test)
{
def("choose_function", choose_function);
}
``
It can be used this way in Python:
``
>>> from make_function_test import *
>>> f = choose_function(1)
>>> g = choose_function(0)
>>> f()
'foo'
>>> g()
'bar'
``
[endsect]
[endsect]

View File

@@ -1,56 +0,0 @@
[section boost/python/manage_new_object.hpp]
[section Class `manage_new_object`]
`manage_new_object` is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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.
``
namespace boost { namespace python
{
struct manage_new_object
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `manage_new_object` metafunctions]
``template <class T> struct apply``
[variablelist
[[Requires][`T` is `U*` for some `U`.]]
[[Returns][`typedef to_python_indirect<T> type;`]]
]
[endsect]
[section Example]
In C++:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/return_value_policy.hpp>
struct Foo {
Foo(int x) : x(x){}
int get_x() { return x; }
int x;
};
Foo* make_foo(int x) { return new Foo(x); }
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
def("make_foo", make_foo, return_value_policy<manage_new_object>())
class_<Foo>("Foo")
.def("get_x", &Foo::get_x)
;
}
``
Python code:
``
>>> from my_module import *
>>> f = make_foo(3) # create a Foo object
>>> f.get_x()
3
``
[endsect]
[endsect]

View File

@@ -1,41 +0,0 @@
[section boost/python/module.hpp]
[section Introduction]
This header provides the basic facilities needed to create a Boost.Python extension module.
[endsect]
[section Macros]
`BOOST_PYTHON_MODULE(name)` is used to declare Python [@http://www.python.org/doc/2.2/ext/methodTable.html#SECTION003400000000000000000 module initialization functions]. The name argument must exactly match the name of the module to be initialized, and must conform to Python's [@http://www.python.org/doc/2.2/ref/identifiers.html identifier naming rules]. Where you would normally write
``
extern "C" void initname()
{
...
}
``
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 [link high_level_components.boost_python_errors_hpp.functions handle_exception()] so that any C++ exceptions generated are safely processeed. During the body of `init_name`, the [link high_level_components.boost_python_scope_hpp current scope] refers to the module being initialized.
[endsect]
[section Examples]
C++ module definition:
``
#include <boost/python/module.hpp>
BOOST_PYTHON_MODULE(xxx)
{
throw "something bad happened"
}
``
Interactive Python:
``
>>> import xxx
Traceback (most recent call last):
File "", line 1, in ?
RuntimeError: Unidentifiable C++ Exception
``
[endsect]
[endsect]

View File

@@ -1,153 +0,0 @@
[section boost/python/numeric.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/dev/doc/devel/lib/typesmapping.html array] type.
[endsect]
[section Class `array`]
Provides access to the array types of [@http://www.pfdubois.com/numpy/ Numerical Python]\ 's [@http://www.pfdubois.com/numpy/#Numeric Numeric] and [@http://stsdas.stsci.edu/numarray/index.html 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 [link concepts.objectwrapper.typewrapper_concept_requirements 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.
``
namespace boost { namespace python { namespace numeric
{
class array : public object
{
public:
object astype();
template <class Type>
object astype(Type const& type_);
template <class Type>
array new_(Type const& type_) const;
template <class Sequence>
void resize(Sequence const& x);
void resize(long x1);
void resize(long x1, long x2);
...
void resize(long x1, long x2,...long xn);
template <class Sequence>
void setshape(Sequence const& x);
void setshape(long x1);
void setshape(long x1, long x2);
...
void setshape(long x1, long x2,...long xn);
template <class Indices, class Values>
void put(Indices const& indices, Values const& values);
template <class Sequence>
object take(Sequence const& sequence, long axis = 0);
template <class File>
void tofile(File const& f) const;
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&);
template <class T1>
explicit array(T1 const& x1);
template <class T1, class T2>
explicit array(T1 const& x1, T2 const& x2);
...
template <class T1, class T2,...class Tn>
explicit array(T1 const& x1, T2 const& x2,...Tn const& xn);
static void set_module_and_type();
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
static void get_module_name();
object argmax(long axis=-1);
object argmin(long axis=-1);
object argsort(long axis=-1);
void byteswap();
object copy() const;
object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
void info() const;
bool is_c_array() const;
bool isbyteswapped() const;
void sort();
object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
object type() const;
char typecode() const;
object getflat() const;
long getrank() const;
object getshape() const;
bool isaligned() const;
bool iscontiguous() const;
long itemsize() const;
long nelements() const;
object nonzero() const;
void ravel();
object repeat(object const& repeats, long axis=0);
void setflat(object const& flat);
void swapaxes(long axis1, long axis2);
str tostring() const;
void transpose(object const& axes = object());
object view() const;
};
}}}
``
[endsect]
[section Class `array` observer functions]
``
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.
``
template <class Type>
array new_(Type const&) const;
``
This function maps to the underlying array type's new() function. It is not called "new" because that is a keyword in C++.
[endsect]
[section Class `array` static functions]
``
static void set_module_and_type(char const* package_path, char const* type_name);
static void set_module_and_type();
``
[variablelist
[[Requires][package_path and type_name, if supplied, is an [link 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()``
[variablelist
[[Effects][Returns the name of the module containing the class that will be held by new `numeric::array` instances.]]
]
[endsect]
[section 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;
}
``
[endsect]
[endsect]

View File

@@ -1,574 +0,0 @@
[section boost/python/object.hpp]
[section Introduction]
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.
[endsect]
[section Class `slice_nil`]
``
class slice_nil;
static const _ = slice_nil();
``
A type that can be used to get the effect of leaving out an index in a Python slice expression:
``
>>> x[:-1]
>>> x[::-1]
``
C++ equivalent:
``
x.slice(_,-1)
x[slice(_,_,-1)]
``
[endsect]
[section Class `const_attribute_policies`]
The policies which are used for proxies representing an attribute access to a const object.
``
namespace boost { namespace python { namespace api
{
struct const_attribute_policies
{
typedef char const* key_type;
static object get(object const& target, char const* key);
};
}}}
``
[endsect]
[section Class `const_attribute_policies` static functions]
``
static object get(object const& target, char const* key);
``
[variablelist
[[Requires][key is an [link ntbs].]]
[[Effects][accesses the attribute of target named by key.]]
[[Returns][An object managing the result of the attribute access.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `attribute_policies`]
The policies which are used for proxies representing an attribute access to a mutable object.
``
namespace boost { namespace python { namespace api
{
struct attribute_policies : const_attribute_policies
{
static object const& set(object const& target, char const* key, object const& value);
static void del(object const&target, char const* key);
};
}}}
``
[endsect]
[section Class `attribute_policies` static functions]
``
static object const& set(object const& target, char const* key, object const& value);
``
[variablelist
[[Requires][key is an [link ntbs].]]
[[Effects][sets the attribute of target named by key to value.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
``
static void del(object const&target, char const* key);
``
[variablelist
[[Requires][key is an [link ntbs].]]
[[Effects][deletes the attribute of target named by key.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `const_objattribute_policies`]
The policies which are used for proxies representing an attribute access to a const object when the attribute name is given as a const object.
``
namespace boost { namespace python { namespace api
{
struct const_objattribute_policies
{
typedef object const& key_type;
static object get(object const& target, object const& key);
};
}}}
``
[endsect]
[section Class `const_objattribute_policies` static functions]
``
static object get(object const& target, object const& key);
``
[variablelist
[[Requires][key is an object holding a string.]]
[[Effects][accesses the attribute of target named by key.]]
[[Returns][An object managing the result of the attribute access.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `objattribute_policies`]
The policies which are used for proxies representing an attribute access to a mutable object when the attribute name is given as a const object.
``
namespace boost { namespace python { namespace api
{
struct objattribute_policies : const_objattribute_policies
{
static object const& set(object const& target, object const& key, object const& value);
static void del(object const&target, object const& key);
};
}}}
``
[endsect]
[section Class `objattribute_policies` static functions]
``
static object const& set(object const& target, object const& key, object const& value);
``
[variablelist
[[Requires][key is an object holding a string.]]
[[Effects][sets the attribute of target named by key to value.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
``
static void del(object const&target, object const& key);
``
[variablelist
[[Requires][key is an object holding a string.]]
[[Effects][deletes the attribute of target named by key.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `const_item_policies`]
The policies which are used for proxies representing an item access (via the Python bracket operators []) to a const object.
``
namespace boost { namespace python { namespace api
{
struct const_item_policies
{
typedef object key_type;
static object get(object const& target, object const& key);
};
}}}
``
[endsect]
[section Class `const_item_policies` static functions]
``
static object get(object const& target, object const& key);
``
[variablelist
[[Effects][accesses the item of target specified by key.]]
[[Returns][An object managing the result of the item access.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `item_policies`]
The policies which are used for proxies representing an item access (via the Python bracket operators []) to a mutable object.
``
namespace boost { namespace python { namespace api
{
struct item_policies : const_item_policies
{
static object const& set(object const& target, object const& key, object const& value);
static void del(object const& target, object const& key);
};
}}}
``
[endsect]
[section Class `item_policies` static functions]
``
static object const& set(object const& target, object const& key, object const& value);
``
[variablelist
[[Effects][sets the item of target specified by key to value.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
``
static void del(object const& target, object const& key);
``
[variablelist
[[Effects][deletes the item of target specified by key.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `const_slice_policies`]
The policies which are used for proxies representing an slice access (via the Python slice notation [x:y]) to a const object.
``
namespace boost { namespace python { namespace api
{
struct const_slice_policies
{
typedef std::pair<handle<>, handle<> > key_type;
static object get(object const& target, key_type const& key);
};
}}}
``
[endsect]
[section Class `const_slice_policies` static functions]
``
static object get(object const& target, key_type const& key);
``
[variablelist
[[Effects][accesses the slice of target specified by key.]]
[[Returns][An object managing the result of the slice access.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class `slice_policies`]
The policies which are used for proxies representing an slice access to a mutable object.
``
namespace boost { namespace python { namespace api
{
struct slice_policies : const_slice_policies
{
static object const& set(object const& target, key_type const& key, object const& value);
static void del(object const& target, key_type const& key);
};
}}}
``
[endsect]
[section Class `slice_policies` static functions]
``
static object const& set(object const& target, key_type const& key, object const& value);
``
[variablelist
[[Effects][sets the slice of target specified by key to value.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
``
static void del(object const& target, key_type const& key);
``
[variablelist
[[Effects][deletes the slice of target specified by key.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] if a Python exception is raised.]]
]
[endsect]
[section Class template `object_operators`]
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.
``
namespace boost { namespace python { namespace api
{
template <class U>
class object_operators
{
public:
// function call
//
object operator()() const;
template <class A0>
object operator()(A0 const&) const;
template <class A0, class A1>
object operator()(A0 const&, A1 const&) const;
...
template <class A0, class A1,...class An>
object operator()(A0 const&, A1 const&,...An const&) const;
detail::args_proxy operator* () const;
object operator()(detail::args_proxy const &args) const;
object operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const;
// truth value testing
//
typedef unspecified bool_type;
operator bool_type() const;
// Attribute access
//
proxy<const_object_attribute> attr(char const*) const;
proxy<object_attribute> attr(char const*);
proxy<const_object_objattribute> attr(object const&) const;
proxy<object_objattribute> attr(object const&);
// item access
//
template <class T>
proxy<const_object_item> operator[](T const& key) const;
template <class T>
proxy<object_item> operator[](T const& key);
// slicing
//
template <class T, class V>
proxy<const_object_slice> slice(T const& start, V const& end) const
template <class T, class V>
proxy<object_slice> slice(T const& start, V const& end);
};
}}}
``
[endsect]
[section Class template `object_operators` observer functions]
``
object operator()() const;
template <class A0>
object operator()(A0 const&) const;
template <class A0, class A1>
object operator()(A0 const&, A1 const&) const;
...
template <class A0, class A1,...class An>
object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
``
[variablelist
[[Effects][`call<object>(object(*static_cast<U*>(this)).ptr(), a1, a2,...aN)`]]
]
``object operator()(detail::args_proxy const &args) const; ``
[variablelist
[[Effects][`call object with arguments given by the tuple args`]]
]
``object operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const;
``
[variablelist
[[Effects][`call object with arguments given by the tuple args, and named arguments given by the dictionary kwds`]]
]
``operator bool_type() const;``
[variablelist
[[Effects][Tests truth value of `*this`.]]
[[Returns][`call<object>(object(*static_cast<U*>(this)).ptr(), a1, a2,...aN)`]]
]
``
proxy<const_object_attribute> attr(char const* name) const;
proxy<object_attribute> attr(char const* name);
``
[variablelist
[[Requires][name is an [link ntbs].]]
[[Effects][accesses the named attribute of *this.]]
[[Returns][a proxy object which binds `object(*static_cast<U*>(this))` as its target, and name as its key.]]
]
``
proxy<const_object_objattribute> attr(const object& name) const;
proxy<object_objattribute> attr(const object& name);
``
[variablelist
[[Requires][name is a object holding a string.]]
[[Effects][accesses the named attribute of `*this`.]]
[[Returns][a proxy object which binds `object(*static_cast<U*>(this))` as its target, and name as its key.]]
]
``
template <class T>
proxy<const_object_item> operator[](T const& key) const;
template <class T>
proxy<object_item> operator[](T const& key);
``
[variablelist
[[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);
``
[variablelist
[[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.]]
]
[endsect]
[section 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.
``
namespace boost { namespace python { namespace api
{
class object : public object_operators<object>
{
public:
object();
object(object const&);
template <class T>
explicit object(T const& x);
~object();
object& operator=(object const&);
PyObject* ptr() const;
bool is_none() const;
};
}}}
``
[endsect]
[section Class `object` constructors and destructor]
``object();``
[variablelist
[[Effects][Constructs an object managing a reference to the Python None object.]]
[[Throws][nothing.]]
]
``template <class T>
explicit object(T const& x);
``
[variablelist
[[Effects][converts x to python and manages a reference to it.]]
[[Throws][[link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set] and sets a Python TypeError exception if no such conversion is possible.]]
]
``
~object();
``
[variablelist
[[Effects][decrements the reference count of the internally-held object.]]
]
[endsect]
[section Class `object` modifiers]
``PyObject* ptr() const;``
[variablelist
[[Returns] [a pointer to the internally-held Python object.]]
]
``bool is_none() const;``
[variablelist
[[Returns] [result of `(ptr() == Py_None)`]]
]
[endsect]
[section 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.
``
namespace boost { namespace python { namespace api
{
template <class Policies>
class proxy : public object_operators<proxy<Policies> >
{
public:
operator object() const;
proxy const& operator=(proxy const&) const;
template <class T>
inline proxy const& operator=(T const& rhs) const;
void del() const;
template <class R>
proxy operator+=(R const& rhs);
template <class R>
proxy operator-=(R const& rhs);
template <class R>
proxy operator*=(R const& rhs);
template <class R>
proxy operator/=(R const& rhs);
template <class R>
proxy operator%=(R const& rhs);
template <class R>
proxy operator<<=(R const& rhs);
template <class R>
proxy operator>>=(R const& rhs);
template <class R>
proxy operator&=(R const& rhs);
template <class R>
proxy operator|=(R const& rhs);
};
}}}
``
[endsect]
[section Class template `proxy` observer functions]
``operator object() const;``
[variablelist
[[Effects][applies `Policies::get(target, key)` with the proxy's target and key objects.]]
]
[endsect]
[section Class template `proxy` modifier functions]
``
proxy const& operator=(proxy const& rhs) const;
template <class T>
inline proxy const& operator=(T const& rhs) const;
``
[variablelist
[[Effects][ `Policies::set(target, key , object(rhs))` with the proxy's target and key objects.]]
]
``
template <class R>
proxy operator+=(R const& rhs);
template <class R>
proxy operator-=(R const& rhs);
template <class R>
proxy operator*=(R const& rhs);
template <class R>
proxy operator/=(R const& rhs);
template <class R>
proxy operator%=(R const& rhs);
template <class R>
proxy operator<<=(R const& rhs);
template <class R>
proxy operator>>=(R const& rhs);
template <class R>
proxy operator&=(R const& rhs);
template <class R>
proxy operator|=(R const& rhs);
``
[variablelist
[[Effects][for a given `operator@=`, `object(*this) @= rhs;`]]
[[Returns][`*this`]]
]
``void del() const;``
[variablelist
[[Effects][Policies::del(target, key ) with the proxy's target and key objects.]]
]
[endsect]
[section Functions]
``
template <class T>
void del(proxy<T> const& x);
``
[variablelist
[[Effects][`x.del()`]]
]
``
template<class L,class R> object operator>(L const&l,R const&r);
template<class L,class R> object operator>=(L const&l,R const&r);
template<class L,class R> object operator<(L const&l,R const&r);
template<class L,class R> object operator<=(L const&l,R const&r);
template<class L,class R> object operator==(L const&l,R const&r);
template<class L,class R> object operator!=(L const&l,R const&r);
``
[variablelist
[[Effects][returns the result of applying the operator to `object(l)` and `object(r)`, respectively, in Python.]]
]
``
template<class L,class R> object operator+(L const&l,R const&r);
template<class L,class R> object operator-(L const&l,R const&r);
template<class L,class R> object operator*(L const&l,R const&r);
template<class L,class R> object operator/(L const&l,R const&r);
template<class L,class R> object operator%(L const&l,R const&r);
template<class L,class R> object operator<<(L const&l,R const&r);
template<class L,class R> object operator>>(L const&l,R const&r);
template<class L,class R> object operator&(L const&l,R const&r);
template<class L,class R> object operator^(L const&l,R const&r);
template<class L,class R> object operator|(L const&l,R const&r);
``
[variablelist
[[Effects][returns the result of applying the operator to `object(l)` and `object(r)`, respectively, in Python.]]
]
``
template<class R> object& operator+=(object&l,R const&r);
template<class R> object& operator-=(object&l,R const&r);
template<class R> object& operator*=(object&l,R const&r);
template<class R> object& operator/=(object&l,R const&r);
template<class R> object& operator%=(object&l,R const&r);
template<class R> object& operator<<=(object&l,R const&r)
template<class R> object& operator>>=(object&l,R const&r);
template<class R> object& operator&=(object&l,R const&r);
template<class R> object& operator^=(object&l,R const&r);
template<class R> object& operator|=(object&l,R const&r);
``
[variablelist
[[Effects][assigns to `l` the result of applying the corresponding Python inplace operator to `l` and `object(r)`, respectively.]]
[[Returns][l]]
]
``long len(object const& obj);``
[variablelist
[[Effects][`PyObject_Length(obj.ptr())`]]
[[Returns][`len()` of object.]]
]
[endsect]
[section Example]
Python code:
``
def sum_items(seq):
result = 0
for x in seq:
result += x
return result
``
C++ version
``
object sum_items(object seq)
{
object result = object(0);
for (int i = 0; i < len(seq); ++i)
result += seq[i];
return result;
}
``
[endsect]
[endsect]

View File

@@ -1,12 +0,0 @@
[chapter Object Wrappers
[quickbook 1.7]
]
[include dict.qbk]
[include list.qbk]
[include long.qbk]
[include numeric.qbk]
[include object.qbk]
[include str.qbk]
[include slice.qbk]
[include tuple.qbk]

View File

@@ -1,31 +0,0 @@
[section boost/python/opaque_pointer_converter.hpp]
[section Introduction]
`opaque<>` registers itself as a converter from Python objects to pointers to undefined types and vice versa.
``
namespace boost { namespace python
{
template<class Pointee>
struct opaque
{
opaque();
};
}}
``
[endsect]
[section Class template `opaque` constructor]
``opaque();``
[variablelist
[[Effects][
* Registers the instance as a [link to_from_python_type_conversion.boost_python_lvalue_from_pytype_.class_template_lvalue_from_pytyp `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 [link to_from_python_type_conversion.boost_python_to_python_converter.class_template_to_python_convert `to_python_converter`] from opaque pointers to Python objects.
]]
]
[note 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.]
[endsect]
[section Macro `BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)`]
This macro must be used to define specializations of the [link utility_and_infrastructure.boost_python_type_id_hpp.functions `type_id`] function which can't be instantiated for incomplete types.
[note The macro must be invoked in every translation unit which uses the opaque converter.]
[endsect]
[endsect]

View File

@@ -1,257 +0,0 @@
[section boost/python/operators.hpp]
[section Introduction]
<boost/python/operators.hpp> provides types and functions for automatically generating Python [@http://www.python.org/doc/ref/specialnames.html special methods] from the corresponding C++ constructs. Most of these constructs are operator expressions, hence the name. To use the facility, substitute the [link high_level_components.boost_python_operators_hpp.object_self self] object for an object of the class type being wrapped in the expression to be exposed, and pass the result to [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu class_<>::def()]. Much of what is exposed in this header should be considered part of the implementation, so is not documented in detail here.
[endsect]
[section Class `self_ns::self_t`]
`self_ns::self_t` is the actual type of the [link high_level_components.boost_python_operators_hpp.object_self 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.
``
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 [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu class_<>::def()]. `x` is an object of the class type being wrapped.
[section `self_t` inplace operators]
In the table below, If `r` is an object of type [link high_level_components.boost_python_operators_hpp.class_template_other other<T>], `y` is an object of type `T`; otherwise, `y` is an object of the same type as `r`.
[table
[[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`]]
]
[endsect]
[section `self_t` comparison functions]
In the tables below, if `r` is of type [link high_level_components.boost_python_operators_hpp.class_self_ns_self_t self_t], `y` is an object of the same type as `x`;
if `l` or `r` is an object of type [link high_level_components.boost_python_operators_hpp.class_template_other 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 [link high_level_components.boost_python_operators_hpp.class_self_ns_self_t 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 [@http://www.python.org/doc/ref/customization.html#l2h-89 reflection rules] for rich comparison operators, and are only used when the corresponding operation is not defined as a method of the y object.
[table
[[C++ Expression][Python Method Name][C++ Implementation][Python Expression (primary, secondary)]]
[[`self == r`][`__eq__`][`x == y`][`x == y`, `y == x`]]
[[`l == self`][`__eq__`][`y == x`][`y == x`, `x == y`]]
[[`self != r`][`__nq__`][`x != y`][`x != y`, `y != x`]]
[[`l != self`][`__nq__`][`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`]]
]
[endsect]
[section `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 [@http://www.python.org/doc/current/ref/numeric-types.html#l2h-152 here].
[table
[[C++ Expression][Python Method Name][C++ Implementation]]
[[`self + r`][`__add__`][`x + y`]]
[[`l + self`][`__radd__`][`y + x`]]
[[`self - r`][`__sub__`][`x - y`]]
[[`l - self`][`__rsub__`][`y - x`]]
[[`self * r`][`__mult__`][`x * y`]]
[[`l * self`][`__rmult__`][`y * x`]]
[[`self / r`][`__div__`][`x / y`]]
[[`l / self`][`__rdiv__`][`y / x`]]
[[`self % r`][`__mod__`][`x % y`]]
[[`l % self`][`__rmod__`][`y % x`]]
[[`self >> r`][`__rshift__`][`x >> y`]]
[[`l >> self`][`__rrshift__`][`y >> x`]]
[[`self << r`][`__lshift__`][`x << y`]]
[[`l << self`][`__rlshift__`][`y << x`]]
[[`self & r`][`__and__`][`x & y`]]
[[`l & self`][`__rand__`][`y & x`]]
[[`self ^ r`][`__xor__`][`x ^ y`]]
[[`l ^ self`][`__rxor__`][`y ^ x`]]
[[`self | r`][`__or__`][`x | y`]]
[[`l | self`][`__ror__`][`y | x`]]
[[`pow(self, r)`][`__pow__`][`x ** y`]]
[[`pow(l, self)`][`__rpow__`][`y ** x`]]
]
[endsect]
[section `self_t` unary operations]
[table
[[C++ Expression][Python Method Name][C++ Implementation]]
[[`-self`][`__neg__`][`-x`]]
[[`+self`][`__pos__`][`+x`]]
[[`~self`][`__invert__`][`~x`]]
[[`not self` or `!self`][`__nonzero__`][`!!x`]]
]
[endsect]
[section `self_t` value operations]
[table
[[C++ Expression][Python Method Name][C++ Implementation]]
[[`int_(self)`][`__int__`][`long(x)`]]
[[`long_(self)`][`__long__`][`PyLong_FromLong(x)`]]
[[`float_(self)`][`__float__`][`double(x)`]]
[[`complex_(self)`][`__complex__`][`std::complex<double>(x)`]]
[[`str(self)`][`__str__`][`lexical_cast<std::string>(x)`]]
[[`repr(self)`][`__repr__`][`lexical_cast<std::string>(x)`]]
]
[endsect]
[endsect]
[section Class template `other`]
Instances of `other<T>` can be used in operator expressions with [link high_level_components.boost_python_operators_hpp.object_self 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.
``
namespace boost { namespace python
{
template <class T>
struct other
{
};
}}
``
[endsect]
[section Class template `detail::operator_`]
Instantiations of `detail::operator_<>` are used as the return type of operator expressions involving [link high_level_components.boost_python_operators_hpp.object_self 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 [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu `class_<>::def()`].
``
namespace boost { namespace python { namespace detail
{
template <unspecified>
struct operator_
{
};
}}}
``
[endsect]
[section Object `self`]
``
namespace boost { namespace python
{
using self_ns::self;
}}
``
[endsect]
[section Example]
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/operators.hpp>
#include <boost/operators.hpp>
struct number
: boost::integer_arithmetic<number>
{
explicit number(long x_) : x(x_) {}
operator long() const { return x; }
template <class T>
number& operator+=(T const& rhs)
{ x += rhs; return *this; }
template <class T>
number& operator-=(T const& rhs)
{ x -= rhs; return *this; }
template <class T>
number& operator*=(T const& rhs)
{ x *= rhs; return *this; }
template <class T>
number& operator/=(T const& rhs)
{ x /= rhs; return *this; }
template <class T>
number& operator%=(T const& rhs)
{ x %= rhs; return *this; }
long x;
};
using namespace boost::python;
BOOST_PYTHON_MODULE(demo)
{
class_<number>("number", init<long>())
// interoperate with self
.def(self += self)
.def(self + self)
.def(self -= self)
.def(self - self)
.def(self *= self)
.def(self * self)
.def(self /= self)
.def(self / self)
.def(self %= self)
.def(self % self)
// Convert to Python int
.def(int_(self))
// interoperate with long
.def(self += long())
.def(self + long())
.def(long() + self)
.def(self -= long())
.def(self - long())
.def(long() - self)
.def(self *= long())
.def(self * long())
.def(long() * self)
.def(self /= long())
.def(self / long())
.def(long() / self)
.def(self %= long())
.def(self % long())
.def(long() % self)
;
}
``
[endsect]
[endsect]

View File

@@ -1,97 +0,0 @@
[section boost/python/overloads.hpp]
[section Introduction]
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
[section 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:
[variablelist
[[docstring][An [link ntbs] whose value will bound to the methods' `__doc__` attribute]]
[[keywords][A [link function_invocation_and_creation.boost_python_args_hpp.introduction.keyword_expressions 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.]]
]
[endsect]
[endsect]
[section 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.
``
X()
X(docstring)
X(docstring, keywords)
X(keywords, docstring)
X()[policies]
X(docstring)[policies]
X(docstring, keywords)[policies]
X(keywords, docstring)[policies]
``
* If policies are supplied, it must be an instance of a type which models [link concepts.callpolicies CallPolicies], and will be used as the result's call policies. Otherwise the result's call policies will be an instance of [link function_invocation_and_creation.models_of_callpolicies.boost_python_default_call_polici `default_call_policies`].
* If docstring is supplied it must be an [link 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 [link function_invocation_and_creation.boost_python_args_hpp.introduction.keyword_expressions 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.
[endsect]
[section Macros]
``
BOOST_PYTHON_FUNCTION_OVERLOADS(name, func_id, min_args, max_args)
``
Expands to the definition of an OverloadDispatcher called name in the current scope which can be used to generate the following function invocation:
``func_id(a1, a2,...ai);``
for all `min_args <= i <= max_args`.
``
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(name, member_name, min_args, max_args)
``
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.
[endsect]
[section Example]
``
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/class.hpp>
#include <boost/python/overloads.hpp>
#include <boost/python/return_internal_reference.hpp>
using namespace boost::python;
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
{
return make_tuple(x, y, z);
}
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
struct Y {};
struct X
{
Y& f(int x, double y = 4.25, char const* z = "wow")
{
return inner;
}
Y inner;
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(f_member_overloads, f, 1, 3)
BOOST_PYTHON_MODULE(args_ext)
{
def("f", f,
f_overloads(
args("x", "y", "z"), "This is f's docstring"
));
class_<Y>("Y")
;
class_<X>("X", "This is X's docstring")
.def("f1", &X::f,
f_member_overloads(
args("x", "y", "z"), "f's docstring"
)[return_internal_reference<>()]
)
;
}
``
[endsect]
[endsect]

View File

@@ -1,159 +0,0 @@
[section Pickle support]
[section Introduction]
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 [@http://www.python.org/doc/current/lib/module-pickle.html 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.
[endsect]
[section The Pickle Interface]
At the user level, the Boost.Python pickle interface involves three special methods:
[variablelist
[[__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 [link object_wrappers.boost_python_tuple_hpp.class_tuple `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.
[endsect]
[section Example]
There are three files in `python/test` that show how to provide pickle support.
[section pickle1.cpp]
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:
Definition of the C++ pickle function:
``
struct world_pickle_suite : boost::python::pickle_suite
{
static
boost::python::tuple
getinitargs(world const& w)
{
return boost::python::make_tuple(w.get_country());
}
};
``
Establishing the Python binding:
``
class_<world>("world", args<const std::string&>())
// ...
.def_pickle(world_pickle_suite())
// ...
``
[endsect]
[section pickle2.cpp]
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:
Definition of the C++ pickle functions:
``
struct world_pickle_suite : boost::python::pickle_suite
{
static
boost::python::tuple
getinitargs(const world& w)
{
// ...
}
static
boost::python::tuple
getstate(const world& w)
{
// ...
}
static
void
setstate(world& w, boost::python::tuple state)
{
// ...
}
};
``
Establishing the Python bindings for the entire suite:
``
class_<world>("world", args<const std::string&>())
// ...
.def_pickle(world_pickle_suite())
// ...
``
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.
[endsect]
[section pickle3.cpp]
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.
[endsect]
[endsect]
[section 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):
``
struct world_pickle_suite : boost::python::pickle_suite
{
// ...
static bool getstate_manages_dict() { return true; }
};
``
Alternatively in Python:
``
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
``
[endsect]
[section 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.
[endsect]
[section 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:
``
class_<world>("world", args<const std::string&>())
// ...
.enable_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
``
See also the tutorial section on injecting additional methods from Python.
[endsect]
[endsect]

View File

@@ -1,47 +0,0 @@
[section boost/python/pointee.hpp]
[section Introduction]
<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.
[endsect]
[section Class template `pointee`]
`pointee<T>` is used by the [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel `class_<...>`] template to deduce the type being held when a pointer or smart pointer type is used as its HeldType argument.
``
namespace boost { namespace python
{
template <class T> struct pointee
{
typedef T::element_type type;
};
// specialization for pointers
template <T> struct pointee<T*>
{
typedef T type;
};
}
``
[endsect]
[section Examples]
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:
``
#include <boost/python/pointee.hpp>
#include <boost/python/class.hpp>
#include <third_party_lib.hpp>
namespace boost { namespace python
{
template <class T> struct pointee<smart_pointer<T> >
{
typedef T type;
};
}}
BOOST_PYTHON_MODULE(pointee_demo)
{
class_<third_party_class, smart_pointer<third_party_class> >("third_party_class")
.def(...)
...
;
}
``
[endsect]
[endsect]

View File

@@ -1,118 +0,0 @@
[section boost/python/ptr.hpp]
[section Introduction]
<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 [link function_invocation_and_creation.boost_python_ptr_hpp.class_template_pointer_wrapper `pointer_wrapper<>`], which can be detected using the [link function_invocation_and_creation.boost_python_ptr_hpp.metafunctions.class_template_is_pointer_wrappe `is_pointer_wrapper<>`] metafunction; [link function_invocation_and_creation.boost_python_ptr_hpp.metafunctions.class_template_unwrap_pointer `unwrap_pointer<>`] is a metafunction which extracts the original pointer type from a `pointer_wrapper<>`. These classes can be thought of as implementation details.
[endsect]
[section Functions]
``
template <class T>
pointer_wrapper<T> ptr(T x);
``
[variablelist
[[Requires][T is a pointer type.]]
[[Returns][pointer_wrapper<T>(x)]]
[[Throws][nothing.]]
]
[endsect]
[section Class template `pointer_wrapper`]
A "type envelope" which is returned by `ptr()`, used to indicate reference semantics for pointers passed to Python callbacks.
``
namespace boost { namespace python
{
template<class Ptr> class pointer_wrapper
{
public:
typedef Ptr type;
explicit pointer_wrapper(Ptr x);
operator Ptr() const;
Ptr get() const;
};
}}
``
[endsect]
[section Class template `pointer_wrapper` types]
``
typedef Ptr type;
``
The type of the pointer being wrapped.
[endsect]
[section Class template `pointer_wrapper` constructors and destructor]
``
explicit pointer_wrapper(Ptr x);
``
[variablelist
[[Requires][`Ptr` is a pointer type]]
[[Effects][Stores `x` in a the `pointer_wrapper<>`. ]]
[[Throws][nothing.]]
]
[endsect]
[section Class template `pointer_wrapper` observer functions]
``
operator Ptr() const;
Ptr get() const;
``
[variablelist
[[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. ]]
]
[endsect]
[section Metafunctions]
[section Class template `is_pointer_wrapper`]
A unary metafunction whose value is true iff its argument is a pointer_wrapper<>.
``
namespace boost { namespace python
{
template<class T> class is_pointer_wrapper
{
static unspecified value = ...;
};
}}
``
[variablelist
[[Returns][`true` iff `T` is a specialization of `pointer_wrapper<>`.
value is an integral constant convertible to bool of unspecified type ]]
]
[endsect]
[section Class template `unwrap_pointer`]
A unary metafunction which extracts the wrapped pointer type from a specialization of pointer_wrapper<>.
``
namespace boost { namespace python
{
template<class T> class unwrap_pointer
{
typedef unspecified type;
};
}}
``
[variablelist
[[Returns][`T::type` if `T` is a specialization of `pointer_wrapper<>`, `T` otherwise ]]
]
[endsect]
[endsect]
[section Example]
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));
}
...
``
[endsect]
[endsect]

View File

@@ -1,194 +0,0 @@
[section boost/python/pytype_function.hpp]
[section Introduction]
To support Pythonic signatures the converters should supply a `get_pytype` function returning a pointer to the associated `PyTypeObject`. See for example [link concepts.resultconverter `ResultConverter`] or [link to_from_python_type_conversion.boost_python_to_python_converter.class_template_to_python_convert.class_template_to_python_convert `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.
[endsect]
[section Class `wrap_pytype`]
This template generates a static `get_pytype` member returning the template parameter.
``
namespace boost { namespace python { namespace converter{
template < PyTypeObject const *pytype >
class wrap_pytype
{
public:
static PyTypeObject const *get_pytype(){return pytype; }
};
}}}
``
[endsect]
[section Class `registered_pytype`]
This template should be used with template parameters which are (possibly decorated) types exported to python using [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel `class_`]. The generated a static `get_pytype` member returns the corresponding python type.
``
namespace boost { namespace python { namespace converter{
template < class T >
class registered_pytype
{
public:
static PyTypeObject const *get_pytype();
};
}}}
``
[endsect]
[section Class `expected_from_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.
``
namespace boost { namespace python { namespace converter{
template < class T >
class expected_from_python_type
{
public:
static PyTypeObject const *get_pytype();
};
}}}
``
[endsect]
[section Class `to_python_target_type`]
This template generates a static `get_pytype` member returning the python type to which `T` can be converted.
``
namespace boost { namespace python { namespace converter{
template < class T >
class to_python_target_type
{
public:
static PyTypeObject const *get_pytype();
};
}}}
``
[endsect]
[section 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.
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)
``
[endsect]
[endsect]

View File

@@ -1,44 +0,0 @@
[section boost/python/raw_function.hpp]
[section Introduction]
`raw_function(...)` is used to convert a function taking a [link object_wrappers.boost_python_tuple_hpp.class_tuple `tuple`] and a [link object_wrappers.boost_python_dict_hpp.class_dict `dict`] into a Python callable object which accepts a variable number of arguments and arbitrary keyword arguments.
[endsect]
[section Function `raw_function`]
``
template <class F>
object raw_function(F f, std::size_t min_args = 0);
``
[variablelist
[[Requires][f(tuple(), dict()) is well-formed.]]
[[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. ]]
]
[endsect]
[section Example]
C++:
``
#include <boost/python/def.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/module.hpp>
#include <boost/python/raw_function.hpp>
using namespace boost::python;
tuple raw(tuple args, dict kw)
{
return make_tuple(args, kw);
}
BOOST_PYTHON_MODULE(raw_test)
{
def("raw", raw_function(raw));
}
``
Python:
``
>>> from raw_test import *
>>> raw(3, 4, foo = 'bar', baz = 42)
((3, 4), {'foo': 'bar', 'baz': 42})
``
[endsect]
[endsect]

View File

@@ -1,75 +0,0 @@
[section boost/python/reference_existing_object.hpp]
[section Class `reference_existing_object`]
`reference_existing_object` is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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 [link concepts.callpolicies CallPolicies] as [link function_invocation_and_creation.models_of_callpolicies.boost_python_with_custodian_and_.class_with_custodian_and_ward `with_custodian_and_ward`]. This class is used in the implementation of [link function_invocation_and_creation.models_of_callpolicies.boost_python_return_internal_ref.class_template_return_internal_r `return_internal_reference`].
``
namespace boost { namespace python
{
struct reference_existing_object
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `reference_existing_object` metafunctions]
``template <class T> struct apply``
[variablelist
[[Requires][`T` is `U&` or `U*` for some `U`.]]
[[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.]]
]
[endsect]
[section 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)
;
}
``
Python code:
``
>>> 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
``
[endsect]
[endsect]

View File

@@ -1,86 +0,0 @@
[section boost/python/register_ptr_to_python.hpp]
[section Introduction]
<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.
[endsect]
[section Function `register_ptr_to_python`]
``
template <class P>
void register_ptr_to_python()
``
[variablelist
[[Requires][`P` is [link concepts.dereferenceable Dereferenceable].]]
[[Effects][Allows conversions to-python of P instances. ]]
]
[endsect]
[section Example]
Here is an example of a module that contains a class A with virtual functions and some functions that work with boost::shared_ptr<A>.
In C++:
``
struct A
{
virtual int f() { return 0; }
};
shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
int Ok( const shared_ptr<A>& a ) { return a->f(); }
int Fail( shared_ptr<A>& a ) { return a->f(); }
struct A_Wrapper: A
{
A_Wrapper(PyObject* self_): self(self_) {}
int f() { return call_method<int>(self, "f"); }
int default_f() { return A::f(); }
PyObject* self;
};
BOOST_PYTHON_MODULE(register_ptr)
{
class_<A, A_Wrapper>("A")
.def("f", &A::f, &A_Wrapper::default_f)
;
def("New", &New);
def("Ok", &Call);
def("Fail", &Fail);
register_ptr_to_python< shared_ptr<A> >();
}
``
In Python:
``
>>> 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
>>>
``
If shared_ptr<A> is registered as follows:
``
class_<A, A_Wrapper, shared_ptr<A> >("A")
.def("f", &A::f, &A_Wrapper::default_f)
;
``
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>
>>>
``
[endsect]

View File

@@ -1,91 +0,0 @@
[section boost/python/return_arg.hpp]
[section Introduction]
`return_arg` and `return_self` instantiations are models of [link concepts.callpolicies `CallPolicies`] which return the specified argument parameter (usually `*this`) of a wrapped (member) function.
[endsect]
[section Class `return_arg`]
[table
[[Parameter][Requirements][Description][Default]]
[[arg_pos][A positive compile-time constant of type `std::size_t`.][the position of the argument to be returned.][1]]
[[Base][A model of [link concepts.callpolicies `CallPolicies`]][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 [link concepts.callpolicies `CallPolicies`].][default_call_policies]]
]
``
namespace boost { namespace python
{
template <size_t arg_pos=1, class Base = default_call_policies>
struct return_arg : Base
{
static PyObject* postcall(PyObject*, PyObject* result);
struct result_converter{ template <class T> struct apply; };
template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{};
};
}}
``
[endsect]
[section Class `return_arg` static functions]
``PyObject* postcall(PyObject* args, PyObject* result);``
[variablelist
[[Requires][`PyTuple_Check(args) != 0` and `PyTuple_Size(args) != 0`]]
[[Returns][PyTuple_GetItem(args,arg_pos-1)]]
]
[endsect]
[section Class template `return_self`]
``
namespace boost { namespace python
{
template <class Base = default_call_policies>
struct return_self
: return_arg<1,Base>
{};
}}
``
[endsect]
[section Example]
C++ module definition:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_arg.hpp>
struct Widget
{
Widget() :sensitive_(true){}
bool get_sensitive() const { return sensitive_; }
void set_sensitive(bool s) { this->sensitive_ = s; }
private:
bool sensitive_;
};
struct Label : Widget
{
Label() {}
std::string get_label() const { return label_; }
void set_label(const std::string &l){ label_ = l; }
private:
std::string label_;
};
using namespace boost::python;
BOOST_PYTHON_MODULE(return_self_ext)
{
class_<widget>("Widget")
.def("sensitive", &Widget::get_sensitive)
.def("sensitive", &Widget::set_sensitive, return_self<>())
;
class_<Label, bases<Widget> >("Label")
.def("label", &Label::get_label)
.def("label", &Label::set_label, return_self<>())
;
}
``
Python code:
``
>>> from return_self_ext import *
>>> l1 = Label().label("foo").sensitive(false)
>>> l2 = Label().sensitive(false).label("foo")
``
[endsect]
[endsect]

View File

@@ -1,62 +0,0 @@
[section boost/python/return_by_value.hpp]
[section Class `return_by_value`]
`return_by_value` is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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.
``
namespace boost { namespace python
{
struct return_by_value
{
template <class T> struct apply;
};
}}
``
[endsect]
[section Class `return_by_value` metafunctions]
``template <class T> struct apply``
[variablelist
[[Returns][`typedef to_python_value<T> type;`]]
]
[endsect]
[section Example]
In C++:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
// classes to wrap
struct Bar { };
Bar global_bar;
// functions to wrap:
Bar b1();
Bar& b2();
Bar const& b3();
// Wrapper code
using namespace boost::python;
template <class R>
void def_void_function(char const* name, R (*f)())
{
def(name, f, return_value_policy<return_by_value>());
}
BOOST_PYTHON_MODULE(my_module)
{
class_<Bar>("Bar");
def_void_function("b1", b1);
def_void_function("b2", b2);
def_void_function("b3", b3);
}
``
Python code:
``
>>> from my_module import *
>>> b = b1() # each of these calls
>>> b = b2() # creates a brand
>>> b = b3() # new Bar object
``
[endsect]
[endsect]

View File

@@ -1,88 +0,0 @@
[section boost/python/return_internal_reference.hpp]
[section Introduction]
`return_internal_reference` instantiations are models of [link concepts.callpolicies `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.
[endsect]
[section Class template `return_internal_reference`]
[table
[[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.][]]
[[Base][A model of [link concepts.callpolicies `CallPolicies`]][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 [link concepts.callpolicies `CallPolicies`].][default_call_policies]]
]
``
namespace boost { namespace python
{
template <std::size_t owner_arg = 1, class Base = default_call_policies>
struct return_internal_reference : Base
{
static PyObject* postcall(PyObject*, PyObject* result);
typedef reference_existing_object result_converter;
};
}}
``
[endsect]
[section Class `return_internal_reference` static functions]
``PyObject* postcall(PyObject* args, PyObject* result);``
[variablelist
[[Requires][`PyTuple_Check(args) != 0`]]
[[Returns][[link function_invocation_and_creation.models_of_callpolicies.boost_python_with_custodian_and_.class_with_custodian_and_ward_st `with_custodian_and_ward_postcall::postcall(args, result)`]]]
]
[endsect]
[section Example]
C++ module definition:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_internal_reference.hpp>
class Bar
{
public:
Bar(int x) : x(x) {}
int get_x() const { return x; }
void set_x(int x) { this->x = x; }
private:
int x;
};
class Foo
{
public:
Foo(int x) : b(x) {}
// Returns an internal reference
Bar const& get_bar() const { return b; }
private:
Bar b;
};
using namespace boost::python;
BOOST_PYTHON_MODULE(internal_refs)
{
class_<Bar>("Bar", init<int>())
.def("get_x", &Bar::get_x)
.def("set_x", &Bar::set_x)
;
class_<Foo>("Foo", init<int>())
.def("get_bar", &Foo::get_bar
, return_internal_reference<>())
;
}
``
Python code:
``
>>> from internal_refs import *
>>> f = Foo(3)
>>> b1 = f.get_bar()
>>> b2 = f.get_bar()
>>> b1.get_x()
3
>>> b2.get_x()
3
>>> b1.set_x(42)
>>> b2.get_x()
42
``
[endsect]
[endsect]

View File

@@ -1,95 +0,0 @@
[section boost/python/return_opaque_pointer.hpp]
[section Class `return_opaqe_pointer`]
return_opaque_pointer is a model of [link concepts.resultconverter.resultconvertergenerator_concept 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 [link to_from_python_type_conversion.boost_python_opaque_pointer_conv.macro_boost_python_opaque_specia `BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID`] macro must be used to define specializations for the [link utility_and_infrastructure.boost_python_type_id_hpp.functions `type_id`] function on the type pointed to by returned pointer.
``
namespace boost { namespace python
{
struct return_opaque_pointer
{
template <class R> struct apply;
};
}}
``
[endsect]
[section Class `return_opaque_pointer` metafunctions]
``template <class T> struct apply``
[variablelist
[[Returns][`detail::opaque_conversion_holder<R> type;`]]
]
[endsect]
[section Example]
In C++:
``
# include <boost/python/return_opaque_pointer.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>
typedef struct opaque_ *opaque;
opaque the_op = ((opaque) 0x47110815);
opaque get () { return the_op; }
void use (opaque op) {
if (op != the_op)
throw std::runtime_error (std::string ("failed"));
}
void failuse (opaque op) {
if (op == the_op)
throw std::runtime_error (std::string ("success"));
}
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
namespace bpl = boost::python;
BOOST_PYTHON_MODULE(opaque_ext)
{
bpl::def (
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
bpl::def ("use", &::use);
bpl::def ("failuse", &::failuse);
}
``
Python code:
``
"""
>>> from opaque_ext import *
>>> #
>>> # Check for correct conversion
>>> use(get())
>>> failuse(get())
Traceback (most recent call last):
...
RuntimeError: success
>>> #
>>> # Check that there is no conversion from integers ...
>>> use(0)
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
>>> #
>>> # ... and from strings to opaque objects
>>> use("")
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
"""
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])
``
[endsect]
[endsect]

View File

@@ -1,59 +0,0 @@
[section boost/python/return_value_policy.hpp]
[section Introduction]
return_value_policy instantiations are simply models of [link concepts.callpolicies `CallPolicies`] which are composed of a [link concepts.resultconverter.resultconvertergenerator_concept `ResultConverterGenerator`] and optional `Base` [link concepts.callpolicies `CallPolicies`].
[endsect]
[section Class template `return_value_policy`]
[table
[[Parameter][Requirements][Default]]
[[ResultConverterGenerator][A model of [link concepts.resultconverter.resultconvertergenerator_concept `ResultConverterGenerator`]][]]
[[Base][A model of [link concepts.callpolicies `CallPolicies`]][default_call_policies]]
]
``
namespace boost { namespace python
{
template <class ResultConverterGenerator, class Base = default_call_policies>
struct return_value_policy : Base
{
typedef ResultConverterGenerator result_converter;
};
}}
``
[endsect]
[section Example]
C++ module definition:
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>
// classes to wrap
struct Bar { int x; }
struct Foo {
Foo(int x) : { b.x = x; }
Bar const& get_bar() const { return b; }
private:
Bar b;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
class_<Bar>("Bar");
class_<Foo>("Foo", init<int>())
.def("get_bar", &Foo::get_bar
, return_value_policy<copy_const_reference>())
;
}
``
Python code:
``
>>> from my_module import *
>>> f = Foo(3) # create a Foo object
>>> b = f.get_bar() # make a copy of the internal Bar object
``
[endsect]
[endsect]

View File

@@ -1,83 +0,0 @@
[section boost/python/scope.hpp]
[section Introduction]
Defines facilities for querying and controlling the Python scope (namespace) which will contain new wrapped classes and functions.
[endsect]
[section 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.
``
namespace boost { namespace python
{
class scope : public object
{
public:
scope(scope const&);
scope(object const&);
scope();
~scope()
private:
void operator=(scope const&);
};
}}
``
[endsect]
[section Class scope constructors and destructor]
``
explicit scope(scope const& x);
explicit scope(object const& x);
``
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.
[endsect]
[section 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)
;
}
``
Interactive Python:
``
>>> import nested
>>> nested.yes
1
>>> y = nested.X.Y()
>>> y.g()
42
``
[endsect]
[endsect]

View File

@@ -1,136 +0,0 @@
[section boost/python/slice.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/doc/2.3.3/api/slice-objects.html `slice`] type.
[endsect]
[section Class `slice`]
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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since `slice` is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `slice` instances as well.
``
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);
};
}}
``
[endsect]
[section Class `slice` constructors]
``slice();``
[variablelist
[[Effects][constructs a slice with default stop, start, and step values. Equivalent to the slice object created as part of the Python expression `base[::]`.]]
[[Throws][nothing]]
]
``
template <typename Int1, typename Int2>
slice(Int1 start, Int2 stop);
``
[variablelist
[[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.]]
]
``
template <typename Int1, typename Int2, typename Int3>
slice(Int1 start, Int2 stop, Int3 step);
``
[variablelist
[[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.]]
]
[endsect]
[section Class `slice` observer functions]
``
object slice::start() const;
object slice::stop() const;
object slice::step() const;
``
[variablelist
[[Effects][None]]
[[Throws][nothing]]
[[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.]]
]
``
template <typename RandomAccessIterator>
slice::range<RandomAccessIterator>
slice::get_indices(
RandomAccessIterator const& begin,
RandomAccessIterator const& end) const;
``
[variablelist
[[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. ]]
]
[endsect]
[section Example]
``
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;
}
``
[endsect]
[endsect]

View File

@@ -1,27 +0,0 @@
[section boost/python/ssize_t.hpp]
[section Introduction]
Python 2.5 introduces a new `Py_ssize_t` typedef and two related macros ([@http://www.python.org/dev/peps/pep-0353/ 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.
[endsect]
[section Typedefs]
Imports `Py_ssize_t` into the `boost::python` namespace if available, or provides an appropriate typedef for backward compatibility:
``
#if PY_VERSION_HEX >= 0x02050000
typedef Py_ssize_t ssize_t;
#else
typedef int ssize_t;
#endif
``
[endsect]
[section Constants]
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:
``
#if PY_VERSION_HEX >= 0x02050000
ssize_t const ssize_t_max = PY_SSIZE_T_MAX;
ssize_t const ssize_t_min = PY_SSIZE_T_MIN;
#else
ssize_t const ssize_t_max = INT_MAX;
ssize_t const ssize_t_min = INT_MIN;
#endif
``
[endsect]
[endsect]

View File

@@ -1,108 +0,0 @@
[section boost/python/stl_iterator.hpp]
[section Introduction]
<boost/python/stl_iterator.hpp> provides types for creating C++ Iterators from [@http://www.python.org/doc/current/lib/typeiter.html Python iterables].
[endsect]
[section Class template `stl_input_iterator`]
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.
[table
[[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.][None]]
]
``
namespace boost { namespace python
{
template <class ValueType>
struct stl_input_iterator
{
typedef std::ptrdiff_t difference_type;
typedef ValueType value_type;
typedef ValueType* pointer;
typedef ValueType reference;
typedef std::input_iterator_tag iterator_category;
stl_input_iterator();
stl_input_iterator(object const& ob);
stl_input_iterator& operator++();
stl_input_iterator operator++(int);
ValueType operator*() const;
friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
private:
object it; // For exposition only
object ob; // For exposition only
};
}}
``
[endsect]
[section Class template `stl_input_iterator` constructors]
``
stl_input_iterator()
``
[variablelist
[[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)``
[variablelist
[[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.]]
]
[endsect]
[section Class template `stl_input_iterator` modifiers]
``
stl_input_iterator &operator++()
``
[variablelist
[[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.]]
[[Returns][`*this`]]
]
``stl_input_iterator &operator++(int)``
[variablelist
[[Effects][`stl_input_iterator tmp = *this; ++*this; return tmp;`]]
[[Postconditions][this is a dereferenceable or past-the-end.]]
]
[endsect]
[section Class template `stl_input_iterator` observers]
``
ValueType operator*() const
``
[variablelist
[[Effects][Returns the current element in the sequence. ]]
[[Returns][`extract<ValueType>(this->ob);`]]
]
``
friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
``
[variablelist
[[Effects][Returns true if both iterators are dereferenceable or if both iterators are past-the-end, false otherwise. ]]
[[Returns][`(lhs.ob == object()) == (rhs.ob == object())`]]
]
``
friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
``
[variablelist
[[Effects][Returns false if both iterators are dereferenceable or if both iterators are past-the-end, true otherwise. ]]
[[Returns][`!(lhs == rhs)`]]
]
[endsect]
[section Example]
``
#include <boost/python/object.hpp>
#include <boost/python/stl_iterator.hpp>
#include <list>
using namespace boost::python;
std::list<int> sequence_to_int_list(object const& ob)
{
stl_input_iterator<int> begin(ob), end;
return std::list<int>(begin, end);
}
``
[endsect]
[endsect]

View File

@@ -1,153 +0,0 @@
[section boost/python/str.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/dev/doc/devel/lib/string-methods.html `str`] type.
[endsect]
[section Class `str`]
Exposes the [@http://www.python.org/dev/doc/devel/lib/string-methods.html 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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since str is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `str` instances as well.
``
namespace boost { namespace python
{
class str : public object
{
public:
str(); // new str
str(char const* s); // new str
str(char const* start, char const* finish); // new str
str(char const* start, std::size_t length); // new str
template <class T>
explicit str(T const& other);
str capitalize() const;
template <class T>
str center(T const& width) const;
template<class T>
long count(T const& sub) const;
template<class T1, class T2>
long count(T1 const& sub,T2 const& start) const;
template<class T1, class T2, class T3>
long count(T1 const& sub,T2 const& start, T3 const& end) const;
object decode() const;
template<class T>
object decode(T const& encoding) const;
template<class T1, class T2>
object decode(T1 const& encoding, T2 const& errors) const;
object encode() const;
template <class T>
object encode(T const& encoding) const;
template <class T1, class T2>
object encode(T1 const& encoding, T2 const& errors) const;
template <class T>
bool endswith(T const& suffix) const;
template <class T1, class T2>
bool endswith(T1 const& suffix, T2 const& start) const;
template <class T1, class T2, class T3>
bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const;
str expandtabs() const;
template <class T>
str expandtabs(T const& tabsize) const;
template <class T>
long find(T const& sub) const;
template <class T1, class T2>
long find(T1 const& sub, T2 const& start) const;
template <class T1, class T2, class T3>
long find(T1 const& sub, T2 const& start, T3 const& end) const;
template <class T>
long index(T const& sub) const;
template <class T1, class T2>
long index(T1 const& sub, T2 const& start) const;
template <class T1, class T2, class T3>
long index(T1 const& sub, T2 const& start, T3 const& end) const;
bool isalnum() const;
bool isalpha() const;
bool isdigit() const;
bool islower() const;
bool isspace() const;
bool istitle() const;
bool isupper() const;
template <class T>
str join(T const& sequence) const;
template <class T>
str ljust(T const& width) const;
str lower() const;
str lstrip() const;
template <class T1, class T2>
str replace(T1 const& old, T2 const& new_) const;
template <class T1, class T2, class T3>
str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const;
template <class T>
long rfind(T const& sub) const;
template <class T1, class T2>
long rfind(T1 const& sub, T2 const& start) const;
template <class T1, class T2, class T3>
long rfind(T1 const& sub, T2 const& start, T3 const& end) const;
template <class T>
long rindex(T const& sub) const;
template <class T1, class T2>
long rindex(T1 const& sub, T2 const& start) const;
template <class T1, class T2, class T3>
long rindex(T1 const& sub, T2 const& start, T3 const& end) const;
template <class T>
str rjust(T const& width) const;
str rstrip() const;
list split() const;
template <class T>
list split(T const& sep) const;
template <class T1, class T2>
list split(T1 const& sep, T2 const& maxsplit) const;
list splitlines() const;
template <class T>
list splitlines(T const& keepends) const;
template <class T>
bool startswith(T const& prefix) const;
template <class T1, class T2>
bool startswidth(T1 const& prefix, T2 const& start) const;
template <class T1, class T2, class T3>
bool startswidth(T1 const& prefix, T2 const& start, T3 const& end) const;
str strip() const;
str swapcase() const;
str title() const;
template <class T>
str translate(T const& table) const;
template <class T1, class T2>
str translate(T1 const& table, T2 const& deletechars) const;
str upper() const;
};
}}
``
[endsect]
[section Example]
``
using namespace boost::python;
str remove_angle_brackets(str x)
{
return x.strip('<').strip('>');
}
``
[endsect]
[endsect]

View File

@@ -1,91 +0,0 @@
[section boost/python/to_python_converter.hpp]
[section Introduction]
`to_python_converter` registers a conversion from objects of a given C++ type into a Python object.
[endsect]
[section 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.
In the table below, x denotes an object of type T
[table
[[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 [link function_invocation_and_creation.function_documentation.boost_python_pytype_function_hpp.example here]).]
]]
``
namespace boost { namespace python
{
template <class T, class Conversion, bool convertion_has_get_pytype_member=false>
struct to_python_converter
{
to_python_converter();
};
}}
``
[section Class template `to_python_converter` constructor]
``to_python_converter();``
[variablelist
[[Effects][Registers a `to_python` converter which uses `Conversion::convert()` to do its work.]]
]
[endsect]
[endsect]
[section 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.
In C++:
``
#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
{
static PyObject* convert(tag const& x)
{
return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
}
static PyTypeObject const* get_pytype()
{
return &noddy_NoddyType;
}
};
BOOST_PYTHON_MODULE(to_python_converter)
{
def("make_tag", make_tag);
to_python_converter<tag, tag_to_noddy, true>(); //"true" because tag_to_noddy has member get_pytype
}
``
In Python:
``
>>> import to_python_converter
>>> def always_none():
... return None
...
>>> def choose_function(x):
... if (x % 2 != 0):
... return to_python_converter.make_tag
... else:
... return always_none
...
>>> a = [ choose_function(x) for x in range(5) ]
>>> b = [ f() for f in a ]
>>> type(b[0])
<type 'NoneType'>
>>> type(b[1])
<type 'Noddy'>
>>> type(b[2])
<type 'NoneType'>
>>> type(b[3])
<type 'Noddy'>
``
[endsect]
[endsect]

View File

@@ -1,65 +0,0 @@
[section boost/python/to_python_indirect.hpp]
[section Introduction]
<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.
[endsect]
[section Class `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.
[table
[[Parameter][Requirements][Description]]
[[T][Either `U cv&` (where cv is any optional cv-qualification) or a [link concepts.dereferenceable 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 [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel `class_`]. ]]
[[MakeHolder][`h = MakeHolder::execute(p);` ][A class whose static `execute()` creates an `instance_holder`. ]]
]
Instantiations of to_python_indirect are models of [link concepts.resultconverter `ResultConverter`].
``
namespace boost { namespace python
{
template <class T, class MakeHolder>
struct to_python_indirect
{
static bool convertible();
PyObject* operator()(T ptr_or_reference) const;
private:
static PyTypeObject* type();
};
}}
``
[endsect]
[section Class `to_python_indirect` observers]
``PyObject* operator()(T x) const;``
[variablelist
[[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.]]
]
[endsect]
[section Class `to_python_indirect` statics]
``bool convertible()``
[variablelist
[[Effects][Returns true iff any module has registered a Python type corresponding to U. ]]
]
[endsect]
[endsect]
[section Example]
This example replicates the functionality of [link function_invocation_and_creation.models_of_resultconvertergenerat.boost_python_reference_existing_.class_reference_existing_object `reference_existing_object`], but without some of the compile-time error checking.
``
struct make_reference_holder
{
typedef boost::python::objects::instance_holder* result_type;
template <class T>
static result_type execute(T* p)
{
return new boost::python::objects::pointer_holder<T*, T>(p);
}
};
struct reference_existing_object
{
// metafunction returning the ResultConverter
template <class T>
struct apply
{
typedef boost::python::to_python_indirect<T,make_reference_holder> type;
};
};
``
[endsect]
[endsect]

View File

@@ -1,34 +0,0 @@
[section boost/python/to_python_value.hpp]
[section Introduction]
`to_python_value` is a model of [link concepts.resultconverter ResultConverter] which copies its argument into a new Python object.
[endsect]
[section Class template `to_python_value`]
``
namespace boost { namespace python
{
template <class T>
struct to_python_value
{
typedef typename add_reference<
typename add_const<T>::type
>::type argument_type;
static bool convertible();
PyObject* operator()(argument_type) const;
};
}}
``
[endsect]
[section Class `to_python_value` observers]
``static bool convertible();``
[variablelist
[[Returns][`true` iff a converter has been registered which can convert `T` to python by-value. ]]
]
``PyObject* operator()(argument_type x) const;``
[variablelist
[[Requires][`convertible() == true`]]
[[Effects][converts `x` to python]]
[[Returns][the resulting Python object iff a converter for `T` has been registered, `0` otherwise. ]]
]
[endsect]
[endsect]

View File

@@ -1,7 +0,0 @@
[chapter Topics
[quickbook 1.7]
]
[include calling.qbk]
[include pickle.qbk]
[include indexing.qbk]

View File

@@ -1,52 +0,0 @@
[section boost/python/tuple.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/doc/current/tut/node7.html#SECTION007300000000000000000`tuple`] type.
[endsect]
[section Class `tuple`]
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 [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since tuple is publicly derived from [link object_wrappers.boost_python_object_hpp.class_object `object`], the public `object` interface applies to `tuple` instances as well.
``
namespace boost { namespace python
{
class tuple : public object
{
// tuple() -> an empty tuple
tuple();
// tuple(sequence) -> tuple initialized from sequence's items
template <class T>
explicit tuple(T const& sequence)
};
}}
``
[endsect]
[section Function `make_tuple`]
``
namespace boost { namespace python
{
tuple make_tuple();
template <class A0>
tuple make_tuple(A0 const& a0);
template <class A0, class A1>
tuple make_tuple(A0 const& a0, A1 const& a1);
...
template <class A0, class A1,...class An>
tuple make_tuple(A0 const& a0, A1 const& a1,...An const& an);
}}
``
[variablelist
[[Effect][Constructs a new tuple object composed of `object(a0),
object(a0),...object(an)`. ]]
]
[endsect]
[section Example]
``
using namespace boost::python;
tuple head_and_tail(object sequence)
{
return make_tuple(sequence[0],sequence[-1]);
}
``
[endsect]
[endsect]

View File

@@ -1,83 +0,0 @@
[section boost/python/type_id.hpp]
[section Introduction]
<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.
[endsect]
[section Class template `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.
``
namespace boost { namespace python
{
class type_info : totally_ordered<type_info>
{
public:
// constructor
type_info(std::type_info const& = typeid(void));
// comparisons
bool operator<(type_info const& rhs) const;
bool operator==(type_info const& rhs) const;
// observers
char const* name() const;
};
}}
``
[section Class template `type_info` constructor]
``type_info(std::type_info const& = typeid(void));``
[variablelist
[[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.]]
]
[endsect]
[section Class template `type_info` comparison]
``bool operator<(type_info const &rhs) const;``
[variablelist
[[Effects][yields a total order over `type_info` objects.]]
]
``bool operator==(type_info const &rhs) const;``
[variablelist
[[Returns][`true` iff the two values describe the same type.]]
[[Note][The use of `totally_ordered<type_info>` as a private base class supplies operators `<=`, `>=`, `>`, and `!=`]]
]
[endsect]
[section Class template `type_info` observers]
``
char const* name() const;
``
[variablelist
[[Returns][The result of calling `name()` on the argument used to construct the object.]]
]
[endsect]
[endsect]
[section Functions]
``
std::ostream& operator<<(std::ostream&s, type_info const&x);
``
[variablelist
[[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.]]
]
``
template <class T> type_info type_id()
``
[variablelist
[[Returns][`type_info(typeid(T))`]]
[[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.]]
]
[endsect]
[section 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>();
}
``
[endsect]
[endsect]

View File

@@ -1,10 +0,0 @@
[chapter Utility and Infrastructure
[quickbook 1.7]
]
[include has_back_reference.qbk]
[include instance_holder.qbk]
[include pointee.qbk]
[include handle.qbk]
[include type_id.qbk]
[include ssize_t.qbk]

View File

@@ -1,72 +0,0 @@
[section boost/python/with_custodian_and_ward.hpp]
[section Introduction]
This header provides facilities for establishing a lifetime dependency between two of a function's Python argument or result objects. The ward object will not be destroyed until after the custodian as long as the custodian object supports [@http://www.python.org/doc/current/lib/module-weakref.html weak references] (Boost.Python extension classes all support weak references). If the custodian object does not support weak references and is not `None`, an appropriate exception will be thrown. The two class templates `with_custodian_and_ward` and `with_custodian_and_ward_postcall` differ in the point at which they take effect.
In order to reduce the chance of inadvertently creating dangling pointers, the default is to do lifetime binding before the underlying C++ object is invoked. However, before invocation the result object is not available, so `with_custodian_and_ward_postcall` is provided to bind lifetimes after invocation. Also, if a C++ exception is thrown after `with_custodian_and_ward<>::precall` but before the underlying C++ object actually stores a pointer, the lifetime of the custodian and ward objects will be artificially bound together, so one might choose `with_custodian_and_ward_postcall` instead, depending on the semantics of the function being wrapped.
Please note that this is not the appropriate tool to use when wrapping functions which transfer ownership of a raw pointer across the function-call boundary. Please see the FAQ if you want to do that.
[endsect]
[section Class `with_custodian_and_ward`]
[table
[[Parameter][Requirements][Description][Default]]
[[custodian][ A positive compile-time constant of `type std::size_t`. ][ The 1-based index of the parameter which is the dependency in the lifetime relationship to be established. 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 C++ object being wrapped is called. ][]]
[[ward][ A positive compile-time constant of type `std::size_t`. ][ The 1-based index of the parameter which is the dependent in the lifetime relationship to be established. If used to wrap a member function, parameter 1 is the target object (`*this`). ][]]
[[Base][ A model of [link concepts.callpolicies `CallPolicies`]][ Used for policy [link concepts.callpolicies.callpolicies_composition composition]. ][default_call_policies]]
]
``
namespace boost { namespace python
{
template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
struct with_custodian_and_ward : Base
{
static bool precall(PyObject* args);
};
}}``
[endsect]
[section Class `with_custodian_and_ward` static functions]
``bool precall(PyObject* args);``
[variablelist
[[Requires][`PyTuple_Check(args) != 0`]]
[[Effects][Makes the lifetime of the argument indicated by ward dependent on the lifetime of the argument indicated by custodian. ]]
[[Returns][false and PyErr_Occurred() != 0 upon failure, true otherwise.]]
]
[endsect]
[section Class `with_custodian_and_ward_postcall`]
[table
[[Parameter][Requirements][Description][Default]]
[[custodian][ A positive compile-time constant of type `std::size_t`. ][ The index of the parameter which is the dependency in the lifetime relationship to be established. Zero indicates the result object; 1 indicates the first argument. 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 C++ object being wrapped is called. ][]]
[[ward][ A positive compile-time constant of type `std::size_t`. ][ The index of the parameter which is the dependent in the lifetime relationship to be established. Zero indicates the result object; 1 indicates the first argument. If used to wrap a member function, parameter 1 is the target object (`*this`). ][]]
[[Base][ A model of [link concepts.callpolicies `CallPolicies`]][ Used for policy [link concepts.callpolicies.callpolicies_composition composition]. ][default_call_policies]]
]
``
namespace boost { namespace python
{
template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
struct with_custodian_and_ward_postcall : Base
{
static PyObject* postcall(PyObject* args, PyObject* result);
};
}}
``
[endsect]
[section Class `with_custodian_and_ward_postcall` static functions]
``PyObject *postcall(PyObject* args, PyObject* result);``
[variablelist
[[Requires][`PyTuple_Check(args) != 0`, `result != 0`]]
[[Effects][Makes the lifetime of the object indicated by ward dependent on the lifetime of the object indicated by custodian. ]]
[[Returns][`0` and `PyErr_Occurred() != 0` upon failure, `true` otherwise. ]]
]
[endsect]
[section Example]
The following example shows how `with_custodian_and_ward_postcall` is used by the library to implement `return_internal_reference`
``
template <std::size_t owner_arg = 1, class Base = default_call_policies>
struct return_internal_reference
: with_custodian_and_ward_postcall<0, owner_arg, Base>
{
typedef reference_existing_object result_converter;
};
``
[endsect]
[endsect]

View File

@@ -1,117 +0,0 @@
[section boost/python/wrapper.hpp]
[section Introduction]
To wrap a class T such that its virtual functions can be "overridden in Python"—so that the corresponding method of a Python derived class will be called when the virtual function is invoked from C++—you must create a C++ wrapper class derived from `T` that overrides those virtual functions so that they call into Python. This header contains classes that can be used to make that job easier.
[endsect]
[section Class `override`]
Encapsulates a Python override of a C++ virtual function. An override object either holds a callable Python object or `None`.
``
namespace boost
{
class override : object
{
public:
unspecified operator() const;
template <class A0>
unspecified operator(A0) const;
template <class A0, class A1>
unspecified operator(A0, A1) const;
...
template <class A0, class A1, ...class An>
unspecified operator(A0, A1, ...An) const;
};
};
``
[endsect]
[section Class `override` observer functions]
``
unspecified operator() const;
template <class A0>
unspecified operator(A0) const;
template <class A0, class A1>
unspecified operator(A0, A1) const;
...
template <class A0, class A1, ...class An>
unspecified operator(A0, A1, ...An) const;
``
[variablelist
[[Effects][If *this holds a callable Python object, it is invoked with the specified arguments in the manner specified here. Otherwise, throws [link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set].]]
[[Returns][An object of unspecified type that holds the Python result of the invocation and, when converted to a C++ type R, attempts to convert that result object to R. If that conversion fails, throws [link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set].]]
]
[endsect]
[section Class template `wrapper`]
Deriving your wrapper class from both `T` and `wrapper<T>` makes writing that derived class easier.
``
namespace boost
{
class wrapper
{
protected:
override get_override(char const* name) const;
};
};
``
[endsect]
[section Class template `wrapper` observer functions]
``override get_override(char const* name) const;``
[variablelist
[[Requires][name is a [link ntbs].]]
[[Returns][If `*this` is the C++ base class subobject of a Python derived class instance that overrides the named function, returns an override object that delegates to the Python override. Otherwise, returns an override object that holds `None`.]]
]
[endsect]
[section Example]
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>
using namespace boost::python;
// Class with one pure virtual function
struct P
{
virtual ~P(){}
virtual char const* f() = 0;
char const* g() { return "P::g()"; }
};
struct PCallback : P, wrapper<P>
{
char const* f()
{
return this->get_override("f")();
}
};
// Class with one non-pure virtual function
struct A
{
virtual ~A(){}
virtual char const* f() { return "A::f()"; }
};
struct ACallback : A, wrapper<A>
{
char const* f()
{
if (override f = this->get_override("f"))
return f();
return A::f();
}
char const* default_f() { return this->A::f(); }
};
BOOST_PYTHON_MODULE_INIT(polymorphism)
{
class_<PCallback,boost::noncopyable>("P")
.def("f", pure_virtual(&P::f))
;
class_<ACallback,boost::noncopyable>("A")
.def("f", &A::f, &ACallback::default_f)
;
}
``
[endsect]
[endsect]

View File

@@ -1,17 +0,0 @@
[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]

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
// See http://www.boost.org/libs/python for documentation.
#ifndef PYTHON_DWA2002810_HPP
# define PYTHON_DWA2002810_HPP
# include <boost/python/args.hpp>
# include <boost/python/args_fwd.hpp>
# include <boost/python/back_reference.hpp>
# include <boost/python/bases.hpp>
# include <boost/python/borrowed.hpp>
# include <boost/python/call.hpp>
# include <boost/python/call_method.hpp>
# include <boost/python/class.hpp>
# include <boost/python/copy_const_reference.hpp>
# include <boost/python/copy_non_const_reference.hpp>
# include <boost/python/data_members.hpp>
# include <boost/python/def.hpp>
# include <boost/python/default_call_policies.hpp>
# include <boost/python/dict.hpp>
# include <boost/python/docstring_options.hpp>
# include <boost/python/enum.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/exception_translator.hpp>
# include <boost/python/exec.hpp>
# include <boost/python/extract.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/has_back_reference.hpp>
# include <boost/python/implicit.hpp>
# include <boost/python/init.hpp>
# include <boost/python/import.hpp>
# include <boost/python/instance_holder.hpp>
# include <boost/python/iterator.hpp>
# include <boost/python/list.hpp>
# include <boost/python/long.hpp>
# include <boost/python/lvalue_from_pytype.hpp>
# include <boost/python/make_constructor.hpp>
# include <boost/python/make_function.hpp>
# include <boost/python/manage_new_object.hpp>
# include <boost/python/module.hpp>
# include <boost/python/numeric.hpp>
# include <boost/python/object.hpp>
# include <boost/python/object_protocol.hpp>
# include <boost/python/object_protocol_core.hpp>
# include <boost/python/opaque_pointer_converter.hpp>
# include <boost/python/operators.hpp>
# include <boost/python/other.hpp>
# include <boost/python/overloads.hpp>
# include <boost/python/pointee.hpp>
# include <boost/python/pure_virtual.hpp>
# include <boost/python/ptr.hpp>
# include <boost/python/raw_function.hpp>
# include <boost/python/reference_existing_object.hpp>
# include <boost/python/register_ptr_to_python.hpp>
# include <boost/python/return_arg.hpp>
# include <boost/python/return_internal_reference.hpp>
# include <boost/python/return_opaque_pointer.hpp>
# include <boost/python/return_value_policy.hpp>
# include <boost/python/scope.hpp>
# include <boost/python/self.hpp>
# include <boost/python/slice.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/stl_iterator.hpp>
# include <boost/python/str.hpp>
# include <boost/python/to_python_converter.hpp>
# include <boost/python/to_python_indirect.hpp>
# include <boost/python/to_python_value.hpp>
# include <boost/python/tuple.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/with_custodian_and_ward.hpp>
#endif // PYTHON_DWA2002810_HPP

View File

@@ -1,76 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef ARG_FROM_PYTHON_DWA2002128_HPP
# define ARG_FROM_PYTHON_DWA2002128_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/converter/arg_from_python.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
# include <boost/type_traits/remove_cv.hpp>
#endif
namespace boost { namespace python {
template <class T>
struct arg_from_python
: converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
typename boost::remove_cv<T>::type
# else
T
# endif
>::type
{
typedef typename converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
typename boost::remove_cv<T>::type
# else
T
# endif
>::type base;
arg_from_python(PyObject*);
};
// specialization for PyObject*
template <>
struct arg_from_python<PyObject*>
{
typedef PyObject* result_type;
arg_from_python(PyObject* p) : m_source(p) {}
bool convertible() const { return true; }
PyObject* operator()() const { return m_source; }
private:
PyObject* m_source;
};
template <>
struct arg_from_python<PyObject* const&>
{
typedef PyObject* const& result_type;
arg_from_python(PyObject* p) : m_source(p) {}
bool convertible() const { return true; }
PyObject*const& operator()() const { return m_source; }
private:
PyObject* m_source;
};
//
// implementations
//
template <class T>
inline arg_from_python<T>::arg_from_python(PyObject* source)
: base(source)
{
}
}} // namespace boost::python
#endif // ARG_FROM_PYTHON_DWA2002128_HPP

View File

@@ -1,149 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef KEYWORDS_DWA2002323_HPP
# define KEYWORDS_DWA2002323_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/args_fwd.hpp>
# include <boost/config.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/type_list.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/type_traits/remove_cv.hpp>
# include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/facilities/intercept.hpp>
# include <boost/preprocessor/iteration/local.hpp>
# include <boost/python/detail/mpl_lambda.hpp>
# include <boost/python/object_core.hpp>
# include <boost/mpl/bool.hpp>
# include <cstddef>
# include <algorithm>
namespace boost { namespace python {
typedef detail::keywords<1> arg;
typedef arg arg_; // gcc 2.96 workaround
namespace detail
{
template <std::size_t nkeywords>
struct keywords_base
{
BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords);
keyword_range range() const
{
return keyword_range(elements, elements + nkeywords);
}
keyword elements[nkeywords];
keywords<nkeywords+1>
operator,(python::arg const &k) const;
keywords<nkeywords + 1>
operator,(char const *name) const;
};
template <std::size_t nkeywords>
struct keywords : keywords_base<nkeywords>
{
};
template <>
struct keywords<1> : keywords_base<1>
{
explicit keywords(char const *name)
{
elements[0].name = name;
}
template <class T>
python::arg& operator=(T const& value)
{
object z(value);
elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
return *this;
}
operator detail::keyword const&() const
{
return elements[0];
}
};
template <std::size_t nkeywords>
inline
keywords<nkeywords+1>
keywords_base<nkeywords>::operator,(python::arg const &k) const
{
keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this);
python::detail::keywords<nkeywords+1> res;
std::copy(l.elements, l.elements+nkeywords, res.elements);
res.elements[nkeywords] = k.elements[0];
return res;
}
template <std::size_t nkeywords>
inline
keywords<nkeywords + 1>
keywords_base<nkeywords>::operator,(char const *name) const
{
return this->operator,(python::arg(name));
}
template<typename T>
struct is_keywords
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<std::size_t nkeywords>
struct is_keywords<keywords<nkeywords> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct is_reference_to_keywords
{
BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value);
typedef typename remove_reference<T>::type deref;
typedef typename remove_cv<deref>::type key_t;
BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value);
BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key));
typedef mpl::bool_<value> type;
BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T))
};
}
inline detail::keywords<1> args(char const* name)
{
return detail::keywords<1>(name);
}
# define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n;
# define BOOST_PP_LOCAL_MACRO(n) \
inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name)) \
{ \
detail::keywords<n> result; \
BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _) \
return result; \
}
# define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY)
# include BOOST_PP_LOCAL_ITERATE()
}} // namespace boost::python
# endif // KEYWORDS_DWA2002323_HPP

View File

@@ -1,52 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef ARGS_FWD_DWA2002927_HPP
# define ARGS_FWD_DWA2002927_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/handle.hpp>
# include <boost/config.hpp>
# include <cstddef>
# include <utility>
namespace boost { namespace python {
namespace detail
{
struct keyword
{
keyword(char const* name_=0)
: name(name_)
{}
char const* name;
handle<> default_value;
};
template <std::size_t nkeywords = 0> struct keywords;
typedef std::pair<keyword const*, keyword const*> keyword_range;
template <>
struct keywords<0>
{
BOOST_STATIC_CONSTANT(std::size_t, size = 0);
static keyword_range range() { return keyword_range(); }
};
namespace error
{
template <int keywords, int function_args>
struct more_keywords_than_function_arguments
{
typedef char too_many_keywords[keywords > function_args ? -1 : 1];
};
}
}
}} // namespace boost::python
#endif // ARGS_FWD_DWA2002927_HPP

View File

@@ -1,71 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef BACK_REFERENCE_DWA2002510_HPP
# define BACK_REFERENCE_DWA2002510_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/object_fwd.hpp>
# include <boost/python/detail/dependent.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
namespace boost { namespace python {
template <class T>
struct back_reference
{
private: // types
typedef typename detail::dependent<object,T>::type source_t;
public:
typedef T type;
back_reference(PyObject*, T);
source_t const& source() const;
T get() const;
private:
source_t m_source;
T m_value;
};
template<typename T>
class is_back_reference
{
public:
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
class is_back_reference<back_reference<T> >
{
public:
BOOST_STATIC_CONSTANT(bool, value = true);
};
//
// implementations
//
template <class T>
back_reference<T>::back_reference(PyObject* p, T x)
: m_source(detail::borrowed_reference(p))
, m_value(x)
{
}
template <class T>
typename back_reference<T>::source_t const& back_reference<T>::source() const
{
return m_source;
}
template <class T>
T back_reference<T>::get() const
{
return m_value;
}
}} // namespace boost::python
#endif // BACK_REFERENCE_DWA2002510_HPP

View File

@@ -1,43 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef BASE_TYPE_TRAITS_DWA2002614_HPP
# define BASE_TYPE_TRAITS_DWA2002614_HPP
# include <boost/python/detail/prefix.hpp>
namespace boost { namespace python {
namespace detail
{
struct unspecialized {};
}
// Derive from unspecialized so we can detect whether traits are
// specialized
template <class T> struct base_type_traits
: detail::unspecialized
{};
template <>
struct base_type_traits<PyObject>
{
typedef PyObject type;
};
template <>
struct base_type_traits<PyTypeObject>
{
typedef PyObject type;
};
template <>
struct base_type_traits<PyMethodObject>
{
typedef PyObject type;
};
}} // namespace boost::python
#endif // BASE_TYPE_TRAITS_DWA2002614_HPP

View File

@@ -1,50 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef BASES_DWA2002321_HPP
# define BASES_DWA2002321_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/python/detail/type_list.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params_with_a_default.hpp>
# include <boost/preprocessor/enum_params.hpp>
namespace boost { namespace python {
# define BOOST_PYTHON_BASE_PARAMS BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, Base)
// A type list for specifying bases
template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_MAX_BASES, typename Base, mpl::void_) >
struct bases : detail::type_list< BOOST_PYTHON_BASE_PARAMS >::type
{};
namespace detail
{
template <class T> struct specifies_bases
: mpl::false_
{
};
template < BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, class Base) >
struct specifies_bases< bases< BOOST_PYTHON_BASE_PARAMS > >
: mpl::true_
{
};
template <class T, class Prev = bases<> >
struct select_bases
: mpl::if_<
specifies_bases<T>
, T
, Prev
>
{
};
}
# undef BOOST_PYTHON_BASE_PARAMS
}} // namespace boost::python
#endif // BASES_DWA2002321_HPP

View File

@@ -1,21 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef BORROWED_DWA2002614_HPP
# define BORROWED_DWA2002614_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/borrowed_ptr.hpp>
namespace boost { namespace python {
template <class T>
inline python::detail::borrowed<T>* borrowed(T* p)
{
return (detail::borrowed<T>*)p;
}
}} // namespace boost::python
#endif // BORROWED_DWA2002614_HPP

View File

@@ -1,83 +0,0 @@
#if !defined(BOOST_PP_IS_ITERATING)
// Copyright David Abrahams 2002.
// 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)
# ifndef CALL_DWA2002411_HPP
# define CALL_DWA2002411_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/type.hpp>
# include <boost/python/converter/arg_to_python.hpp>
# include <boost/python/converter/return_from_python.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/void_return.hpp>
# include <boost/preprocessor/comma_if.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/debug/line.hpp>
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
namespace boost { namespace python {
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
, converter::arg_to_python<A##n>(a##n).get()
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call.hpp>))
# include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
}} // namespace boost::python
# endif // CALL_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call.hpp)
# endif
# define N BOOST_PP_ITERATION()
template <
class R
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
>
typename detail::returnable<R>::type
call(PyObject* callable
BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)
, boost::type<R>* = 0
)
{
PyObject* const result =
PyEval_CallFunction(
callable
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
);
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
// argument for passing to PyEval_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.
converter::return_from_python<R> converter;
return converter(result);
}
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -1,83 +0,0 @@
#if !defined(BOOST_PP_IS_ITERATING)
// Copyright David Abrahams 2002.
// 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)
# ifndef CALL_METHOD_DWA2002411_HPP
# define CALL_METHOD_DWA2002411_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/type.hpp>
# include <boost/python/converter/arg_to_python.hpp>
# include <boost/python/converter/return_from_python.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/void_return.hpp>
# include <boost/preprocessor/comma_if.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/debug/line.hpp>
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
namespace boost { namespace python {
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
, converter::arg_to_python<A##n>(a##n).get()
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call_method.hpp>))
# include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
}} // namespace boost::python
# endif // CALL_METHOD_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
# endif
# define N BOOST_PP_ITERATION()
template <
class R
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
>
typename detail::returnable<R>::type
call_method(PyObject* self, char const* name
BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)
, boost::type<R>* = 0
)
{
PyObject* const result =
PyEval_CallMethod(
self
, const_cast<char*>(name)
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
);
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
// argument for passing to PyEval_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.
converter::return_from_python<R> converter;
return converter(result);
}
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif // BOOST_PP_IS_ITERATING

View File

@@ -1,106 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef CAST_DWA200269_HPP
# define CAST_DWA200269_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type.hpp>
# include <boost/python/base_type_traits.hpp>
# include <boost/python/detail/convertible.hpp>
namespace boost { namespace python {
namespace detail
{
template <class Source, class Target> inline Target* upcast_impl(Source*, Target*);
template <class Source, class Target>
inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*)
{
return p;
}
template <class Source, class Target>
inline Target* upcast(Source* p, no_convertible, no_convertible, Target*)
{
typedef typename base_type_traits<Source>::type base;
return detail::upcast_impl((base*)p, (Target*)0);
}
template <bool is_same = true>
struct upcaster
{
template <class T>
static inline T* execute(T* x, T*) { return x; }
};
template <>
struct upcaster<false>
{
template <class Source, class Target>
static inline Target* execute(Source* x, Target*)
{
return detail::upcast(
x, detail::convertible<Target*>::check(x)
, detail::convertible<Source*>::check((Target*)0)
, (Target*)0);
}
};
template <class Target, class Source>
inline Target* downcast(Source* p, yes_convertible)
{
return static_cast<Target*>(p);
}
template <class Target, class Source>
inline Target* downcast(Source* p, no_convertible, boost::type<Target>* = 0)
{
typedef typename base_type_traits<Source>::type base;
return (Target*)detail::downcast<base>(p, convertible<Source*>::check((base*)0));
}
template <class T>
inline void assert_castable(boost::type<T>* = 0)
{
typedef char must_be_a_complete_type[sizeof(T)];
}
template <class Source, class Target>
inline Target* upcast_impl(Source* x, Target*)
{
typedef typename add_cv<Source>::type src_t;
typedef typename add_cv<Target>::type target_t;
bool const same = is_same<src_t,target_t>::value;
return detail::upcaster<same>::execute(x, (Target*)0);
}
}
template <class Target, class Source>
inline Target* upcast(Source* x, Target* = 0)
{
detail::assert_castable<Source>();
detail::assert_castable<Target>();
return detail::upcast_impl(x, (Target*)0);
}
template <class Target, class Source>
inline Target* downcast(Source* x, Target* = 0)
{
detail::assert_castable<Source>();
detail::assert_castable<Target>();
return detail::downcast<Target>(x, detail::convertible<Source*>::check((Target*)0));
}
}} // namespace boost::python
#endif // CAST_DWA200269_HPP

View File

@@ -1,612 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef CLASS_DWA200216_HPP
# define CLASS_DWA200216_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/noncopyable.hpp>
# include <boost/python/class_fwd.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/object.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/data_members.hpp>
# include <boost/python/make_function.hpp>
# include <boost/python/signature.hpp>
# include <boost/python/init.hpp>
# include <boost/python/args_fwd.hpp>
# include <boost/python/object/class_metadata.hpp>
# include <boost/python/object/pickle_support.hpp>
# include <boost/python/object/add_to_namespace.hpp>
# include <boost/python/detail/overloads_fwd.hpp>
# include <boost/python/detail/operator_id.hpp>
# include <boost/python/detail/def_helper.hpp>
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/unwrap_type_id.hpp>
# include <boost/python/detail/unwrap_wrapper.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_member_function_pointer.hpp>
# include <boost/type_traits/is_polymorphic.hpp>
# include <boost/mpl/size.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/mpl/not.hpp>
# include <boost/detail/workaround.hpp>
# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \
/* pro9 reintroduced the bug */ \
|| (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
# endif
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# include <boost/mpl/and.hpp>
# include <boost/type_traits/is_member_pointer.hpp>
# endif
namespace boost { namespace python {
template <class DerivedVisitor> class def_visitor;
enum no_init_t { no_init };
namespace detail
{
// This function object is used with mpl::for_each to write the id
// of the type a pointer to which is passed as its 2nd compile-time
// argument. into the iterator pointed to by its runtime argument
struct write_type_id
{
write_type_id(type_info**p) : p(p) {}
// Here's the runtime behavior
template <class T>
void operator()(T*) const
{
*(*p)++ = type_id<T>();
}
type_info** p;
};
template <class T>
struct is_data_member_pointer
: mpl::and_<
is_member_pointer<T>
, mpl::not_<is_member_function_pointer<T> >
>
{};
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
# define BOOST_PYTHON_YES_DATA_MEMBER , int
# define BOOST_PYTHON_NO_DATA_MEMBER , ...
# else
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
# define BOOST_PYTHON_YES_DATA_MEMBER
# define BOOST_PYTHON_NO_DATA_MEMBER
# endif
namespace error
{
//
// A meta-assertion mechanism which prints nice error messages and
// backtraces on lots of compilers. Usage:
//
// assertion<C>::failed
//
// where C is an MPL metafunction class
//
template <class C> struct assertion_failed { };
template <class C> struct assertion_ok { typedef C failed; };
template <class C>
struct assertion
: mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
{};
//
// Checks for validity of arguments used to define virtual
// functions with default implementations.
//
template <class Default>
void not_a_derived_class_member(Default) {}
template <class T, class Fn>
struct virtual_function_default
{
template <class Default>
static void
must_be_derived_class_member(Default const&)
{
// https://svn.boost.org/trac/boost/ticket/5803
//typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
typedef typename assertion<is_polymorphic<T> >::failed test1;
# endif
typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
not_a_derived_class_member<Default>(Fn());
}
};
}
}
// This is the primary mechanism through which users will expose
// C++ classes to Python.
template <
class W // class being wrapped
, class X1 // = detail::not_specified
, class X2 // = detail::not_specified
, class X3 // = detail::not_specified
>
class class_ : public objects::class_base
{
public: // types
typedef objects::class_base base;
typedef class_<W,X1,X2,X3> self;
typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
typedef W wrapped_type;
private: // types
// A helper class which will contain an array of id objects to be
// passed to the base class constructor
struct id_vector
{
typedef typename metadata::bases bases;
id_vector()
{
// Stick the derived class id into the first element of the array
ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
// Write the rest of the elements into succeeding positions.
type_info* p = ids + 1;
mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
}
BOOST_STATIC_CONSTANT(
std::size_t, size = mpl::size<bases>::value + 1);
type_info ids[size];
};
friend struct id_vector;
public: // constructors
// Construct with the class name, with or without docstring, and default __init__() function
class_(char const* name, char const* doc = 0);
// Construct with class name, no docstring, and an uncallable __init__ function
class_(char const* name, no_init_t);
// Construct with class name, docstring, and an uncallable __init__ function
class_(char const* name, char const* doc, no_init_t);
// Construct with class name and init<> function
template <class DerivedT>
inline class_(char const* name, init_base<DerivedT> const& i)
: base(name, id_vector::size, id_vector().ids)
{
this->initialize(i);
}
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
: base(name, id_vector::size, id_vector().ids, doc)
{
this->initialize(i);
}
public: // member functions
// Generic visitation
template <class Derived>
self& def(def_visitor<Derived> const& visitor)
{
visitor.visit(*this);
return *this;
}
// Wrap a member function or a non-member function which can take
// a T, T cv&, or T cv* as its first parameter, a callable
// python object, or a generic visitor.
template <class F>
self& def(char const* name, F f)
{
this->def_impl(
detail::unwrap_wrapper((W*)0)
, name, f, detail::def_helper<char const*>(0), &f);
return *this;
}
template <class A1, class A2>
self& def(char const* name, A1 a1, A2 const& a2)
{
this->def_maybe_overloads(name, a1, a2, &a2);
return *this;
}
template <class Fn, class A1, class A2>
self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
{
// The arguments are definitely:
// def(name, function, policy, doc_string)
// def(name, function, doc_string, policy)
this->def_impl(
detail::unwrap_wrapper((W*)0)
, name, fn
, detail::def_helper<A1,A2>(a1,a2)
, &fn);
return *this;
}
template <class Fn, class A1, class A2, class A3>
self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
{
this->def_impl(
detail::unwrap_wrapper((W*)0)
, name, fn
, detail::def_helper<A1,A2,A3>(a1,a2,a3)
, &fn);
return *this;
}
//
// Data member access
//
template <class D>
self& def_readonly(char const* name, D const& d, char const* doc=0)
{
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D const& d, char const* doc=0)
{
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readonly(char const* name, D& d, char const* doc=0)
{
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D& d, char const* doc=0)
{
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
// Property creation
template <class Get>
self& add_property(char const* name, Get fget, char const* docstr = 0)
{
base::add_property(name, this->make_getter(fget), docstr);
return *this;
}
template <class Get, class Set>
self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
{
base::add_property(
name, this->make_getter(fget), this->make_setter(fset), docstr);
return *this;
}
template <class Get>
self& add_static_property(char const* name, Get fget)
{
base::add_static_property(name, object(fget));
return *this;
}
template <class Get, class Set>
self& add_static_property(char const* name, Get fget, Set fset)
{
base::add_static_property(name, object(fget), object(fset));
return *this;
}
template <class U>
self& setattr(char const* name, U const& x)
{
this->base::setattr(name, object(x));
return *this;
}
// Pickle support
template <typename PickleSuiteType>
self& def_pickle(PickleSuiteType const& x)
{
error_messages::must_be_derived_from_pickle_suite(x);
detail::pickle_suite_finalize<PickleSuiteType>::register_(
*this,
&PickleSuiteType::getinitargs,
&PickleSuiteType::getstate,
&PickleSuiteType::setstate,
PickleSuiteType::getstate_manages_dict());
return *this;
}
self& enable_pickling()
{
this->base::enable_pickling_(false);
return *this;
}
self& staticmethod(char const* name)
{
this->make_method_static(name);
return *this;
}
private: // helper functions
// Builds a method for this class around the given [member]
// function pointer or object, appropriately adjusting the type of
// the first signature argument so that if f is a member of a
// (possibly not wrapped) base class of T, an lvalue argument of
// type T will be required.
//
// @group PropertyHelpers {
template <class F>
object make_getter(F f)
{
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
detail::unwrap_wrapper((W*)0)
, f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
);
}
template <class F>
object make_setter(F f)
{
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
detail::unwrap_wrapper((W*)0)
, f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
);
}
template <class T, class F>
object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
{
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
}
template <class T, class D, class B>
object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
{
D T::*pm = pm_;
return python::make_getter(pm);
}
template <class T, class D, class B>
object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
{
D T::*pm = pm_;
return python::make_setter(pm);
}
template <class T, class F>
object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
{
return x;
}
// }
template <class D, class B>
self& def_readonly_impl(
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
{
return this->add_property(name, pm_, doc);
}
template <class D, class B>
self& def_readwrite_impl(
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
{
return this->add_property(name, pm_, pm_, doc);
}
template <class D>
self& def_readonly_impl(
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, python::make_getter(d));
}
template <class D>
self& def_readwrite_impl(
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
}
template <class DefVisitor>
inline void initialize(DefVisitor const& i)
{
metadata::register_(); // set up runtime metadata/conversions
typedef typename metadata::holder holder;
this->set_instance_size( objects::additional_instance_size<holder>::value );
this->def(i);
}
inline void initialize(no_init_t)
{
metadata::register_(); // set up runtime metadata/conversions
this->def_no_init();
}
//
// These two overloads discriminate between def() as applied to a
// generic visitor and everything else.
//
// @group def_impl {
template <class T, class Helper, class LeafVisitor, class Visitor>
inline void def_impl(
T*
, char const* name
, LeafVisitor
, Helper const& helper
, def_visitor<Visitor> const* v
)
{
v->visit(*this, name, helper);
}
template <class T, class Fn, class Helper>
inline void def_impl(
T*
, char const* name
, Fn fn
, Helper const& helper
, ...
)
{
objects::add_to_namespace(
*this
, name
, make_function(
fn
, helper.policies()
, helper.keywords()
, detail::get_signature(fn, (T*)0)
)
, helper.doc()
);
this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
}
// }
//
// These two overloads handle the definition of default
// implementation overloads for virtual functions. The second one
// handles the case where no default implementation was specified.
//
// @group def_default {
template <class Fn, class Helper>
inline void def_default(
char const* name
, Fn
, Helper const& helper
, mpl::bool_<true>)
{
detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
helper.default_implementation());
objects::add_to_namespace(
*this, name,
make_function(
helper.default_implementation(), helper.policies(), helper.keywords())
);
}
template <class Fn, class Helper>
inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
{ }
// }
//
// These two overloads discriminate between def() as applied to
// regular functions and def() as applied to the result of
// BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
// discriminate.
//
// @group def_maybe_overloads {
template <class OverloadsT, class SigT>
void def_maybe_overloads(
char const* name
, SigT sig
, OverloadsT const& overloads
, detail::overloads_base const*)
{
// convert sig to a type_list (see detail::get_signature in signature.hpp)
// before calling detail::define_with_defaults.
detail::define_with_defaults(
name, overloads, *this, detail::get_signature(sig));
}
template <class Fn, class A1>
void def_maybe_overloads(
char const* name
, Fn fn
, A1 const& a1
, ...)
{
this->def_impl(
detail::unwrap_wrapper((W*)0)
, name
, fn
, detail::def_helper<A1>(a1)
, &fn
);
}
// }
};
//
// implementations
//
template <class W, class X1, class X2, class X3>
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
: base(name, id_vector::size, id_vector().ids, doc)
{
this->initialize(init<>());
// select_holder::assert_default_constructible();
}
template <class W, class X1, class X2, class X3>
inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
: base(name, id_vector::size, id_vector().ids)
{
this->initialize(no_init);
}
template <class W, class X1, class X2, class X3>
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
: base(name, id_vector::size, id_vector().ids, doc)
{
this->initialize(no_init);
}
}} // namespace boost::python
# undef BOOST_PYTHON_DATA_MEMBER_HELPER
# undef BOOST_PYTHON_YES_DATA_MEMBER
# undef BOOST_PYTHON_NO_DATA_MEMBER
# undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
#endif // CLASS_DWA200216_HPP

View File

@@ -1,24 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
#ifndef CLASS_FWD_DWA200222_HPP
# define CLASS_FWD_DWA200222_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/not_specified.hpp>
namespace boost { namespace python {
template <
class T // class being wrapped
// arbitrarily-ordered optional arguments. Full qualification needed for MSVC6
, class X1 = ::boost::python::detail::not_specified
, class X2 = ::boost::python::detail::not_specified
, class X3 = ::boost::python::detail::not_specified
>
class class_;
}} // namespace boost::python
#endif // CLASS_FWD_DWA200222_HPP

Some files were not shown because too many files have changed in this diff Show More