mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
24 Commits
boost-1.88
...
boost-1.32
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43fb8c5a0f | ||
|
|
1a221e80b2 | ||
|
|
41deb6855c | ||
|
|
72207ba070 | ||
|
|
f20ff9f9d6 | ||
|
|
1afc3580a3 | ||
|
|
ee1328e10d | ||
|
|
9ccde24cff | ||
|
|
168c8c692a | ||
|
|
3540d4fcf4 | ||
|
|
0ccded7df3 | ||
|
|
f81c779823 | ||
|
|
8e4c69ee5a | ||
|
|
3af8dc41d7 | ||
|
|
1286cb0527 | ||
|
|
baf3c962f3 | ||
|
|
6c7c9fb61f | ||
|
|
8aeaed2e5f | ||
|
|
44b1c14d7e | ||
|
|
d65734aac4 | ||
|
|
c99bd3ab00 | ||
|
|
259a258123 | ||
|
|
858055cd0a | ||
|
|
197bb21fb7 |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,947 +1 @@
|
||||
+++++++++++++++++++++++++++++++++++++++++++
|
||||
Building Hybrid Systems with Boost.Python
|
||||
+++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
:Author: David Abrahams
|
||||
:Contact: dave@boost-consulting.com
|
||||
:organization: `Boost Consulting`_
|
||||
:date: $Date$
|
||||
|
||||
: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:: python_cpp_mix.jpg
|
||||
|
||||
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
|
||||
This file has been moved to http://www.boost-consulting.com/writing/bpl.txt.
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -29,13 +29,24 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>8 Sept 2004</dt>
|
||||
<dt>19 November 2004 - 1.32 release</dt>
|
||||
|
||||
<dd>
|
||||
<ul>
|
||||
<li>Updated to use the Boost Software License.</li>
|
||||
<li>A new, <a href="tutorial/doc/html/python/exposing.html#python.class_virtual_functions">better method of wrapping classes with virtual functions</a> has been implemented.</li>
|
||||
<li>Support for upcoming GCC symbol export control features have been folded in, thanks to Niall Douglas.</li>
|
||||
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
|
||||
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i> of function parameter types part of the function type has been worked around.</li>
|
||||
<li>Components used by other libraries have been moved out of <code>python/detail</code> and into <code> boost/detail</code> to improve dependency relationships.</li>
|
||||
<li>Miscellaneous bug fixes and compiler workarounds.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>8 Sept 2004</dt>
|
||||
|
||||
<dd>
|
||||
Support for Python's Bool type, thanks to <a
|
||||
mailto="dholth-at-fastmail.fm">Daniel Holth</a>.
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt>11 Sept 2003</dt>
|
||||
@@ -189,12 +200,12 @@ BOOST_PYTHON_MODULE(test)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
11 September 2003
|
||||
19 November 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@
|
||||
15 July, 2003</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2002-2003. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -2,4 +2,7 @@ project boost/libs/python/doc/tutorial/doc ;
|
||||
import boostbook : boostbook ;
|
||||
|
||||
boostbook tutorial : tutorial.xml
|
||||
: <xsl:param>boost.root=../../../../../..
|
||||
<xsl:param>boost.libraries=../../../../../libraries.htm
|
||||
;
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE catalog
|
||||
PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
|
||||
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
|
||||
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||
<rewriteURI uriStartString="http://www.boost.org/tools/boostbook/dtd/" rewritePrefix="file:///C:/dev/boost/tools/boostbook/dtd//"/>
|
||||
<rewriteURI uriStartString="http://docbook.sourceforge.net/release/xsl/current/" rewritePrefix="file:///C:/dev/tools/boostbook/docbook-xsl-1.65.1/"/>
|
||||
<rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2/" rewritePrefix="file:///C:/dev/tools/boostbook/docbook-xml-4.2/"/>
|
||||
</catalog>
|
||||
@@ -3,24 +3,23 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter 1. python 1.0</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../boost.png"></td>
|
||||
<td align="center"><a href="../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||
<div class="chapter" lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div class="titlepage"><div>
|
||||
<div><h2 class="title">
|
||||
<a name="python"></a>Chapter 1. python 1.0</h2></div>
|
||||
<div><div class="author"><h3 class="author">
|
||||
@@ -30,17 +29,17 @@
|
||||
<span class="firstname">David</span> <span class="surname">Abrahams</span>
|
||||
</h3></div></div>
|
||||
<div><p class="copyright">Copyright © 2002-2004 Joel de Guzman, David Abrahams</p></div>
|
||||
<div><div class="legalnotice"><p>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id376569"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
</a>)
|
||||
|
||||
</p></div></div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
@@ -53,7 +52,6 @@
|
||||
<dt><span class="section"><a href="python/exposing.html#python.class_properties">Class Properties</a></span></dt>
|
||||
<dt><span class="section"><a href="python/exposing.html#python.inheritance">Inheritance</a></span></dt>
|
||||
<dt><span class="section"><a href="python/exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
|
||||
<dt><span class="section"><a href="python/exposing.html#python.deriving_a_python_class">Deriving a Python Class</a></span></dt>
|
||||
<dt><span class="section"><a href="python/exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
|
||||
<dt><span class="section"><a href="python/exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||
</dl></dd>
|
||||
@@ -84,11 +82,8 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.quickstart"></a>QuickStart</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.quickstart"></a>QuickStart</h2></div></div></div>
|
||||
<p>
|
||||
The Boost Python Library is a framework for interfacing Python and
|
||||
C++. It allows you to quickly and seamlessly expose C++ classes
|
||||
@@ -101,7 +96,7 @@ metaprogramming techniques simplifies its syntax for users, so that
|
||||
wrapping code takes on the look of a kind of declarative interface
|
||||
definition language (IDL).</p>
|
||||
<a name="quickstart.hello_world"></a><h2>
|
||||
<a name="id344076"></a>Hello World</h2>
|
||||
<a name="id376600"></a>Hello World</h2>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A C++
|
||||
Function:</p>
|
||||
|
||||
@@ -3,31 +3,28 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Embedding</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="object.html" title=" Object Interface">
|
||||
<link rel="prev" href="object.html" title=" Object Interface">
|
||||
<link rel="next" href="iterators.html" title="Iterators">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.embedding"></a>Embedding</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.embedding"></a>Embedding</h2></div></div></div>
|
||||
<div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div>
|
||||
<p>
|
||||
By now you should know how to use Boost.Python to call your C++ code from
|
||||
@@ -42,7 +39,7 @@ the gaps. However, Boost.Python already makes embedding a lot easier and,
|
||||
in a future version, it may become unnecessary to touch the Python/C API at
|
||||
all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
|
||||
<a name="embedding.building_embedded_programs"></a><h2>
|
||||
<a name="id428755"></a>Building embedded programs</h2>
|
||||
<a name="id460514"></a>Building embedded programs</h2>
|
||||
<p>
|
||||
To be able to use embedding in your programs, they have to be linked to
|
||||
both Boost.Python's and Python's static link library.</p>
|
||||
@@ -51,7 +48,8 @@ Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
|
||||
variants are called <tt class="literal">boost_python.lib</tt> (for release builds) and
|
||||
<tt class="literal">boost_python_debug.lib</tt> (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See <a href="../../../../building.html%20Building" target="_top">and Testing</a> on how to do this.</p>
|
||||
you probably haven't built Boost.Python yet. See
|
||||
<a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this.</p>
|
||||
<p>
|
||||
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
@@ -77,7 +75,7 @@ In a Jamfile, all the above boils down to:</p>
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
</tt></pre>
|
||||
<a name="embedding.getting_started"></a><h2>
|
||||
<a name="id428846"></a>Getting started</h2>
|
||||
<a name="id460605"></a>Getting started</h2>
|
||||
<p>
|
||||
Being able to build is nice, but there is nothing to build yet. Embedding
|
||||
the Python interpreter into one of your C++ programs requires these 4
|
||||
@@ -103,11 +101,8 @@ Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656"
|
||||
(Of course, there can be other C++ code between all of these steps.)</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in our programs, lets see how to put it to use...</b></span></em></span></p></blockquote></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||
<p>
|
||||
As you probably already know, objects in Python are reference-counted.
|
||||
Naturally, the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted.
|
||||
@@ -115,10 +110,10 @@ There is a difference however. While the reference-counting is fully
|
||||
automatic in Python, the Python/C API requires you to do it
|
||||
<a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by hand</a>. This is
|
||||
messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the <a href="../../v2/handle.html" target="_top">handle</a> and
|
||||
Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a> and
|
||||
<a href="../../../../v2/object.html" target="_top">object</a> class templates to automate the process.</p>
|
||||
<a name="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
|
||||
<a name="id428977"></a>Reference-counting handles and objects</h2>
|
||||
<a name="id460737"></a>Reference-counting handles and objects</h2>
|
||||
<p>
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span> or as a <span class="emphasis"><em>new reference</em></span>. Which of
|
||||
@@ -151,7 +146,7 @@ discuss in the next section.</p>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||
<a name="id429281"></a>Running Python code</h2>
|
||||
<a name="id461039"></a>Running Python code</h2>
|
||||
<p>
|
||||
To run Python code from C++ there is a family of functions in the API
|
||||
starting with the PyRun prefix. You can find the full list of these
|
||||
@@ -166,7 +161,7 @@ The <tt class="literal">start</tt> parameter is the start symbol from the Python
|
||||
for interpreting the code. The possible values are:</p>
|
||||
<div class="informaltable">
|
||||
<h4>
|
||||
<a name="id429442"></a><span class="table-title">Start symbols</span>
|
||||
<a name="id461201"></a><span class="table-title">Start symbols</span>
|
||||
</h4>
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
@@ -229,7 +224,7 @@ containing a phrase that is well-known in programming circles.</p>
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s.</p>
|
||||
<a name="using_the_interpreter.beyond_handles"></a><h2>
|
||||
<a name="id429881"></a>Beyond handles</h2>
|
||||
<a name="id461639"></a>Beyond handles</h2>
|
||||
<p>
|
||||
It's nice that <tt class="literal">handle</tt> manages the reference counting details for us, but
|
||||
other than that it doesn't do much. Often we'd like to have a more useful
|
||||
@@ -271,12 +266,12 @@ int</span><span class="identifier"> five_squared</span><span class="special"> =<
|
||||
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt>
|
||||
perform.</p>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||
<a name="id430451"></a>Exception handling</h2>
|
||||
<a name="id462209"></a>Exception handling</h2>
|
||||
<p>
|
||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
function returns a null pointer. Constructing a <tt class="literal">handle</tt> out of this null
|
||||
pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||
so basically, the Python exception is automatically translated into a
|
||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
function returns a null pointer. Constructing a <tt class="literal">handle</tt> out of this null
|
||||
pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||
so basically, the Python exception is automatically translated into a
|
||||
C++ exception when using <tt class="literal">handle</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">try</span><span class="special">
|
||||
{</span><span class="identifier">
|
||||
@@ -295,14 +290,13 @@ catch</span><span class="special">(</span><span class="identifier">error_already
|
||||
// handle the exception in some way
|
||||
</span><span class="special">}</span></tt></pre>
|
||||
<p>
|
||||
The <tt class="literal">error_already_set</tt> exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
<a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception handling functions</a>
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
<a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a> to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">
|
||||
standard exceptions</a>:</p>
|
||||
The <tt class="literal">error_already_set</tt> exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
<a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception handling functions</a>
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
<a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a> to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html%20standard" target="_top">exceptions</a>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
if</span><span class="special"> (</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span><span class="special">
|
||||
@@ -316,11 +310,11 @@ standard exceptions</a>:</p>
|
||||
}</span><span class="special">
|
||||
}</span></tt></pre>
|
||||
<p>
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)</p>
|
||||
<p>
|
||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception when it is constructed, you
|
||||
can use the <a href="../../v2/handle.html#allow_null-spec" target="_top">allow_null</a> function in the same
|
||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception when it is constructed, you
|
||||
can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a> function in the same
|
||||
way you'd use borrowed:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">handle</span><span class="special"><></span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">
|
||||
"5/0"</span><span class="special">
|
||||
|
||||
@@ -3,31 +3,28 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exception Translation</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="iterators.html" title="Iterators">
|
||||
<link rel="prev" href="iterators.html" title="Iterators">
|
||||
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.exception"></a> Exception Translation</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.exception"></a> Exception Translation</h2></div></div></div>
|
||||
<p>
|
||||
All C++ exceptions must be caught at the boundary with Python code. This
|
||||
boundary is the point where C++ meets Python. Boost.Python provides a
|
||||
|
||||
@@ -3,38 +3,34 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="hello.html" title=" Building Hello World">
|
||||
<link rel="prev" href="hello.html" title=" Building Hello World">
|
||||
<link rel="next" href="functions.html" title="Functions">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.exposing"></a> Exposing Classes</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.exposing"></a> Exposing Classes</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="exposing.html#python.constructors">Constructors</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.class_data_members">Class Data Members</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.class_properties">Class Properties</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.inheritance">Inheritance</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.deriving_a_python_class">Deriving a Python Class</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
|
||||
<dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||
</dl></div>
|
||||
@@ -71,11 +67,8 @@ may use our class <tt class="literal">World</tt> in Python. Here's a sample Pyth
|
||||
>>></span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="char">
|
||||
'howdy'</span></tt></pre>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.constructors"></a>Constructors</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||
<p>
|
||||
Our previous example didn't have any explicit constructors.
|
||||
Since <tt class="literal">World</tt> is declared as a plain struct, it has an implicit default
|
||||
@@ -128,11 +121,8 @@ This actually adds an <tt class="literal"><span class="underline">_init</span>_<
|
||||
Python RuntimeError exception.</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.class_data_members"></a>Class Data Members</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
|
||||
<p>
|
||||
Data members may also be exposed to Python so that they can be
|
||||
accessed as attributes of the corresponding Python class. Each data
|
||||
@@ -166,11 +156,8 @@ as <span class="bold"><b>read-write</b></span>.</p>
|
||||
</tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.class_properties"></a>Class Properties</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_properties"></a>Class Properties</h3></div></div></div>
|
||||
<p>
|
||||
In C++, classes with public data members are usually frowned
|
||||
upon. Well designed classes that take advantage of encapsulation hide
|
||||
@@ -205,11 +192,8 @@ since the <tt class="literal">rovalue</tt> setter member function is not passed
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span><span class="special"> &</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.inheritance"></a>Inheritance</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.inheritance"></a>Inheritance</h3></div></div></div>
|
||||
<p>
|
||||
In the previous examples, we dealt with classes that are not polymorphic.
|
||||
This is not often the case. Much of the time, we will be wrapping
|
||||
@@ -241,10 +225,13 @@ Now we can inform Boost.Python of the inheritance relationship between
|
||||
Doing so, we get some things for free:</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
|
||||
Derived automatically inherits all of Base's Python methods
|
||||
(wrapped C++ member functions)
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt> objects which have been passed to Python via a pointer or reference to <tt class="literal">Base</tt> can be passed where a pointer or reference to <tt class="literal">Derived</tt> is expected.
|
||||
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt> objects which have been passed to
|
||||
Python via a pointer or reference to <tt class="literal">Base</tt> can be passed where a pointer
|
||||
or reference to <tt class="literal">Derived</tt> is expected.
|
||||
</li>
|
||||
</ol></div>
|
||||
<p>
|
||||
@@ -258,53 +245,64 @@ instances of class <tt class="literal">Derived</tt>. In such cases, we use
|
||||
<tt class="literal">return_value_policy<manage_new_object></tt> to instruct Python to adopt
|
||||
the pointer to <tt class="literal">Base</tt> and hold the instance in a new Python <tt class="literal">Base</tt>
|
||||
object until the the Python object is destroyed. We shall see more of
|
||||
Boost.Python <a href="functions.html#python.call_policies" target="_top">call policies</a> later.</p>
|
||||
Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call policies</a> later.</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="comment">// Tell Python to take ownership of factory's result
|
||||
</span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span><span class="identifier"> factory</span><span class="special">,</span><span class="identifier">
|
||||
return_value_policy</span><span class="special"><</span><span class="identifier">manage_new_object</span><span class="special">>());</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
|
||||
<p>
|
||||
In this section, we shall learn how to make functions behave
|
||||
polymorphically through virtual functions. Continuing our example, let us
|
||||
add a virtual function to our <tt class="literal">Base</tt> class:</p>
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our <tt class="literal">Base</tt> class:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
virtual</span><span class="special"> ~</span><span class="identifier">Base</span><span class="special">()</span><span class="special"> {}</span><span class="keyword">
|
||||
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> =</span><span class="number"> 0</span><span class="special">;</span><span class="special">
|
||||
};</span></tt></pre>
|
||||
<p>
|
||||
Since <tt class="literal">f</tt> is a pure virtual function, <tt class="literal">Base</tt> is now an abstract
|
||||
class. Given an instance of our class, the free function <tt class="literal">call_f</tt>
|
||||
calls some implementation of this virtual function in a concrete
|
||||
derived class:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">int</span><span class="identifier"> call_f</span><span class="special">(</span><span class="identifier">Base</span><span class="special">&</span><span class="identifier"> b</span><span class="special">)</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> b</span><span class="special">.</span><span class="identifier">f</span><span class="special">();</span><span class="special"> }</span></tt></pre>
|
||||
<p>
|
||||
To allow this function to be implemented in a Python derived class, we
|
||||
need to create a class wrapper:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="identifier">
|
||||
BaseWrap</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span><span class="identifier"> self_</span><span class="special">)</span><span class="special">
|
||||
:</span><span class="identifier"> self</span><span class="special">(</span><span class="identifier">self_</span><span class="special">)</span><span class="special"> {}</span><span class="keyword">
|
||||
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> call_method</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">self</span><span class="special">,</span><span class="string"> "f"</span><span class="special">);</span><span class="special"> }</span><span class="identifier">
|
||||
PyObject</span><span class="special">*</span><span class="identifier"> self</span><span class="special">;</span><span class="special">
|
||||
};</span><span class="keyword">
|
||||
|
||||
|
||||
struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="identifier">
|
||||
BaseWrap</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span><span class="identifier"> self_</span><span class="special">)</span><span class="special">
|
||||
:</span><span class="identifier"> self</span><span class="special">(</span><span class="identifier">self_</span><span class="special">)</span><span class="special"> {}</span><span class="identifier">
|
||||
BaseWrap</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span><span class="identifier"> self_</span><span class="special">,</span><span class="identifier"> Base</span><span class="keyword"> const</span><span class="special">&</span><span class="identifier"> copy</span><span class="special">)</span><span class="special">
|
||||
:</span><span class="identifier"> Base</span><span class="special">(</span><span class="identifier">copy</span><span class="special">),</span><span class="identifier"> self</span><span class="special">(</span><span class="identifier">self_</span><span class="special">)</span><span class="special"> {}</span><span class="keyword">
|
||||
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> call_method</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">self</span><span class="special">,</span><span class="string"> "f"</span><span class="special">);</span><span class="special"> }</span><span class="keyword">
|
||||
int</span><span class="identifier"> default_f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special"> }</span><span class="comment"> // <<=== ***ADDED***
|
||||
</span><span class="identifier"> PyObject</span><span class="special">*</span><span class="identifier"> self</span><span class="special">;</span><span class="special">
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||
design. In principle, it should be possible to expose the interface for a 3rd
|
||||
party library without changing it. It is not ideal to add anything to our class
|
||||
<tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when you have a virtual function that's going to be overridden in
|
||||
Python and called polymorphically <span class="bold"><b>from C++</b></span>, we'll need to add some
|
||||
scaffoldings to make things work properly. What we'll do is write a class
|
||||
wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt> that will unintrusively hook into the virtual
|
||||
functions so that a Python override may be called:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">,</span><span class="identifier"> wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
return</span><span class="keyword"> this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span><span class="special">
|
||||
}</span><span class="special">
|
||||
};</span></tt></pre>
|
||||
<p>
|
||||
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>, we also multiply-
|
||||
inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>). The
|
||||
<tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes the job of wrapping classes that are meant to
|
||||
overridden in Python, easier.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td>
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png"></span> MSVC6/7 Workaround<p></p>
|
||||
<p></p>
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:<p></p>
|
||||
<p></p>
|
||||
<tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt> in effect calls the
|
||||
corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.</p>
|
||||
<p>
|
||||
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><span class="special">
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> pure_virtual</span><span class="special">(&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span><span class="special">
|
||||
;</span></tt></pre>
|
||||
<p><tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a pure virtual
|
||||
function.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td>
|
||||
@@ -315,126 +313,19 @@ many object oriented languages uses the term <span class="bold"><b>methods</b></
|
||||
correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Our class wrapper <tt class="literal">BaseWrap</tt> is derived from <tt class="literal">Base</tt>. Its overridden
|
||||
virtual member function <tt class="literal">f</tt> in effect calls the corresponding method
|
||||
of the Python object <tt class="literal">self</tt>, which is a pointer back to the Python
|
||||
<tt class="literal">Base</tt> object holding our <tt class="literal">BaseWrap</tt> instance.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td>
|
||||
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Why do we need BaseWrap?</b></span><p></p>
|
||||
<p></p>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p><span class="emphasis"><em>You may ask</em></span>, "Why do we need the <tt class="literal">BaseWrap</tt> derived class? This could
|
||||
have been designed so that everything gets done right inside of
|
||||
Base."</p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p>
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an
|
||||
existing C++ design. In principle, it should be possible to expose the
|
||||
interface for a 3rd party library without changing it. To unintrusively
|
||||
hook into the virtual functions so that a Python override may be called, we
|
||||
must use a derived class.</p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p>
|
||||
Note however that you don't need to do this to get methods overridden
|
||||
in Python to behave virtually when called <span class="emphasis"><em>from</em></span><span class="bold"><b>Python</b></span>. The only
|
||||
time you need to do the <tt class="literal">BaseWrap</tt> dance is when you have a virtual
|
||||
function that's going to be overridden in Python and called
|
||||
polymorphically <span class="emphasis"><em>from</em></span><span class="bold"><b>C++</b></span>.]</p>
|
||||
<p>
|
||||
Wrapping <tt class="literal">Base</tt> and the free function <tt class="literal">call_f</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span><span class="identifier"> BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">,</span><span class="identifier"> no_init</span><span class="special">)</span><span class="special">
|
||||
;</span><span class="identifier">
|
||||
def</span><span class="special">(</span><span class="string">"call_f"</span><span class="special">,</span><span class="identifier"> call_f</span><span class="special">);</span></tt></pre>
|
||||
<p>
|
||||
Notice that we parameterized the <tt class="literal">class_</tt> template with <tt class="literal">BaseWrap</tt> as the
|
||||
second parameter. What is <tt class="literal">noncopyable</tt>? Without it, the library will try
|
||||
to create code for converting Base return values of wrapped functions to
|
||||
Python. To do that, it needs Base's copy constructor... which isn't
|
||||
available, since Base is an abstract class.</p>
|
||||
<p>
|
||||
In Python, let us try to instantiate our <tt class="literal">Base</tt> class:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="identifier">
|
||||
RuntimeError</span><span class="special">:</span><span class="identifier"> This</span><span class="keyword"> class</span><span class="identifier"> cannot</span><span class="identifier"> be</span><span class="identifier"> instantiated</span><span class="identifier"> from</span><span class="identifier"> Python</span></tt></pre>
|
||||
<p>
|
||||
Why is it an error? <tt class="literal">Base</tt> is an abstract class. As such it is advisable
|
||||
to define the Python wrapper with <tt class="literal">no_init</tt> as we have done above. Doing
|
||||
so will disallow abstract base classes such as <tt class="literal">Base</tt> to be instantiated.</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.deriving_a_python_class"></a>Deriving a Python Class</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
|
||||
<p>
|
||||
Continuing, we can derive from our base class Base in Python and override
|
||||
the virtual function in Python. Before we can do that, we have to set up
|
||||
our <tt class="literal">class_</tt> wrapper as:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span><span class="identifier"> BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><span class="special">
|
||||
;</span></tt></pre>
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
wrapped using Boost.Python's <a href="../../../../v2//wrapper.html" target="_top">class wrapper</a>
|
||||
facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions instead, the
|
||||
mechanism is a bit different.</p>
|
||||
<p>
|
||||
Otherwise, we have to suppress the Base class' <tt class="literal">no_init</tt> by adding an
|
||||
<tt class="literal"><span class="underline">_init</span>_()</tt> method to all our derived classes. <tt class="literal">no_init</tt> actually adds
|
||||
an <tt class="literal"><span class="underline">_init</span>_</tt> method that raises a Python RuntimeError exception.</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="keyword"> class</span><span class="identifier"> Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span><span class="special">
|
||||
...</span><span class="identifier"> def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="special">
|
||||
...</span><span class="keyword"> return</span><span class="number"> 42</span><span class="special">
|
||||
...</span></tt></pre>
|
||||
<p>
|
||||
Cool eh? A Python class deriving from a C++ class!</p>
|
||||
<p>
|
||||
Let's now make an instance of our Python class <tt class="literal">Derived</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> derived</span><span class="special"> =</span><span class="identifier"> Derived</span><span class="special">()</span></tt></pre>
|
||||
<p>
|
||||
Calling <tt class="literal">derived.f()</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number">
|
||||
42</span></tt></pre>
|
||||
<p>
|
||||
Will yield the expected result. Finally, calling calling the free function
|
||||
<tt class="literal">call_f</tt> with <tt class="literal">derived</tt> as argument:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> call_f</span><span class="special">(</span><span class="identifier">derived</span><span class="special">)</span><span class="number">
|
||||
42</span></tt></pre>
|
||||
<p>
|
||||
Will also yield the expected result.</p>
|
||||
<p>
|
||||
Here's what's happening:</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<tt class="literal">call_f(derived)</tt> is called in Python
|
||||
</li>
|
||||
<li>
|
||||
This corresponds to <tt class="literal">def("call_f", call_f);</tt>. Boost.Python dispatches this call.
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">int call_f(Base& b) { return b.f(); }</tt> accepts the call.
|
||||
</li>
|
||||
<li>
|
||||
The overridden virtual function <tt class="literal">f</tt> of <tt class="literal">BaseWrap</tt> is called.
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">call_method<int>(self, "f");</tt> dispatches the call back to Python.
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">def f(self): return 42</tt> is finally called.
|
||||
</li>
|
||||
</ol></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
Recall that in the <a href="exposing.html#class_virtual_functions" target="_top">previous section</a>, we
|
||||
wrapped a class with a pure virtual function that we then implemented in
|
||||
C++ or Python classes derived from it. Our base class:</p>
|
||||
Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous section</a>, we
|
||||
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||
Python classes derived from it. Our base class:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> =</span><span class="number"> 0</span><span class="special">;</span><span class="special">
|
||||
@@ -444,31 +335,46 @@ had a pure virtual function <tt class="literal">f</tt>. If, however, its member
|
||||
not declared as pure virtual:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
virtual</span><span class="special"> ~</span><span class="identifier">Base</span><span class="special">()</span><span class="special"> {}</span><span class="keyword">
|
||||
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="number"> 0</span><span class="special">;</span><span class="special"> }</span><span class="special">
|
||||
};</span></tt></pre>
|
||||
<p>
|
||||
and instead had a default implementation that returns <tt class="literal">0</tt>, as shown above,
|
||||
we need to add a forwarding function that calls the <tt class="literal">Base</tt> default virtual
|
||||
function <tt class="literal">f</tt> implementation:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">
|
||||
{</span><span class="identifier">
|
||||
BaseWrap</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span><span class="identifier"> self_</span><span class="special">)</span><span class="special">
|
||||
:</span><span class="identifier"> self</span><span class="special">(</span><span class="identifier">self_</span><span class="special">)</span><span class="special"> {}</span><span class="keyword">
|
||||
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> call_method</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">self</span><span class="special">,</span><span class="string"> "f"</span><span class="special">);</span><span class="special"> }</span><span class="keyword">
|
||||
int</span><span class="identifier"> default_f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special"> }</span><span class="comment"> // <<=== ***ADDED***
|
||||
</span><span class="identifier"> PyObject</span><span class="special">*</span><span class="identifier"> self</span><span class="special">;</span><span class="special">
|
||||
We wrap it this way:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">,</span><span class="identifier"> wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special">
|
||||
{</span><span class="keyword">
|
||||
if</span><span class="special"> (</span><span class="identifier">override</span><span class="identifier"> f</span><span class="special"> =</span><span class="keyword"> this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span><span class="keyword">
|
||||
return</span><span class="identifier"> f</span><span class="special">();</span><span class="comment"> // *note*
|
||||
</span><span class="keyword"> return</span><span class="identifier"> Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special">
|
||||
}</span><span class="keyword">
|
||||
|
||||
int</span><span class="identifier"> default_f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="keyword"> this</span><span class="special">-></span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special"> }</span><span class="special">
|
||||
};</span></tt></pre>
|
||||
<p>
|
||||
Then, Boost.Python needs to keep track of 1) the dispatch function <tt class="literal">f</tt> and
|
||||
2) the forwarding function to its default implementation <tt class="literal">default_f</tt>.
|
||||
There's a special <tt class="literal">def</tt> function for this purpose. Here's how it is
|
||||
applied to our example above:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">,</span><span class="identifier"> BaseWrap</span><span class="special">,</span><span class="identifier"> BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><span class="special">
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="special"> &</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span><span class="special"> &</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span></tt></pre>
|
||||
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now, we have to check if there is an
|
||||
override for <tt class="computeroutput"><span class="identifier">f</span></tt>. If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td>
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png"></span> MSVC6/7 Workaround<p></p>
|
||||
<p></p>
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
|
||||
with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<p></p>
|
||||
<p></p>
|
||||
<tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special"><</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Note that we are allowing <tt class="literal">Base</tt> objects to be instantiated this time,
|
||||
unlike before where we specifically defined the <tt class="literal">class_<Base></tt> with
|
||||
<tt class="literal">no_init</tt>.</p>
|
||||
Finally, exposing:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><span class="special">
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="special"> &</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span><span class="special"> &</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span><span class="special">
|
||||
;</span></tt></pre>
|
||||
<p>
|
||||
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>.
|
||||
Boost.Python needs to keep track of 1) the dispatch function <tt class="literal">f</tt> and 2) the
|
||||
forwarding function to its default implementation <tt class="literal">default_f</tt>. There's a
|
||||
special <tt class="literal">def</tt> function for this purpose.</p>
|
||||
<p>
|
||||
In Python, the results would be as expected:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="special">
|
||||
@@ -485,23 +391,12 @@ Calling <tt class="literal">base.f()</tt>:</p>
|
||||
Calling <tt class="literal">derived.f()</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number">
|
||||
42</span></tt></pre>
|
||||
<p>
|
||||
Calling <tt class="literal">call_f</tt>, passing in a <tt class="literal">base</tt> object:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> call_f</span><span class="special">(</span><span class="identifier">base</span><span class="special">)</span><span class="number">
|
||||
0</span></tt></pre>
|
||||
<p>
|
||||
Calling <tt class="literal">call_f</tt>, passing in a <tt class="literal">derived</tt> object:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> call_f</span><span class="special">(</span><span class="identifier">derived</span><span class="special">)</span><span class="number">
|
||||
42</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h2>
|
||||
<a name="id420103"></a>Python Operators</h2>
|
||||
<a name="id451830"></a>Python Operators</h2>
|
||||
<p>
|
||||
C is well known for the abundance of operators. C++ extends this to the
|
||||
extremes by allowing operator overloading. Boost.Python takes advantage of
|
||||
@@ -538,7 +433,7 @@ you might need to interact with in an operator expression is (cheaply)
|
||||
default-constructible. You can use <tt class="literal">other<T>()</tt> in place of an actual
|
||||
<tt class="literal">T</tt> instance when writing "self expressions".</p>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||
<a name="id420789"></a>Special Methods</h2>
|
||||
<a name="id452516"></a>Special Methods</h2>
|
||||
<p>
|
||||
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python supports all of the
|
||||
standard special method names supported by real Python class instances. A
|
||||
|
||||
@@ -3,31 +3,28 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Functions</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="prev" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="object.html" title=" Object Interface">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.functions"></a>Functions</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.functions"></a>Functions</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="functions.html#python.call_policies">Call Policies</a></span></dt>
|
||||
<dt><span class="section"><a href="functions.html#python.overloading">Overloading</a></span></dt>
|
||||
@@ -68,11 +65,8 @@ But before you do, you might want to fire up Python 2.2 or later and type
|
||||
Namespaces are one honking great idea -- let's do more of those!
|
||||
</tt></pre>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.call_policies"></a>Call Policies</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.call_policies"></a>Call Policies</h3></div></div></div>
|
||||
<p>
|
||||
In C++, we often deal with arguments and return types such as pointers
|
||||
and references. Such primitive types are rather, ummmm, low level and
|
||||
@@ -178,7 +172,7 @@ A reference to <tt class="literal">y.x</tt> is returned
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
</ol></div>
|
||||
<a name="call_policies.call_policies"></a><h2>
|
||||
<a name="id422411"></a>Call Policies</h2>
|
||||
<a name="id454162"></a>Call Policies</h2>
|
||||
<p>
|
||||
Call Policies may be used in situations such as the example detailed above.
|
||||
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
|
||||
@@ -253,11 +247,8 @@ Boost.Python v1 approach
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.overloading"></a>Overloading</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.overloading"></a>Overloading</h3></div></div></div>
|
||||
<p>
|
||||
The following illustrates a scheme for manually wrapping an overloaded
|
||||
member functions. Of course, the same technique can be applied to wrapping
|
||||
@@ -301,11 +292,8 @@ With these in hand, we can proceed to define and wrap this for Python:</p>
|
||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx4</span><span class="special">)</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
||||
pointers carry no default argument info. Take a function <tt class="literal">f</tt> with default
|
||||
@@ -323,7 +311,7 @@ to retrieve the default arguments:</p>
|
||||
</span></tt></pre>
|
||||
<p>
|
||||
Because of this, when wrapping C++ code, we had to resort to manual
|
||||
wrapping as outlined in the <a href="functions.html#overloading" target="_top">previous section</a>, or
|
||||
wrapping as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>, or
|
||||
writing thin wrappers:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="comment">// write "thin wrappers"
|
||||
</span><span class="keyword">int</span><span class="identifier"> f1</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> x</span><span class="special">)</span><span class="special"> {</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span><span class="special"> }</span><span class="keyword">
|
||||
@@ -347,7 +335,7 @@ are overloaded with a common sequence of initial arguments
|
||||
</li>
|
||||
</ul></div>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
||||
<a name="id424225"></a>BOOST_PYTHON_FUNCTION_OVERLOADS</h2>
|
||||
<a name="id455979"></a>BOOST_PYTHON_FUNCTION_OVERLOADS</h2>
|
||||
<p>
|
||||
Boost.Python now has a way to make it easier. For instance, given a function:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="keyword">int</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> b</span><span class="special"> =</span><span class="number"> 1</span><span class="special">,</span><span class="keyword"> unsigned</span><span class="identifier"> c</span><span class="special"> =</span><span class="number"> 2</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> d</span><span class="special"> =</span><span class="number"> 3</span><span class="special">)</span><span class="special">
|
||||
@@ -366,7 +354,7 @@ and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
|
||||
automatically add all the foo variants for us:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="identifier"> foo_overloads</span><span class="special">());</span></tt></pre>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||
<a name="id424504"></a>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2>
|
||||
<a name="id456259"></a>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2>
|
||||
<p>
|
||||
Objects here, objects there, objects here there everywhere. More frequently
|
||||
than anything else, we need to expose member functions of our classes to
|
||||
@@ -398,7 +386,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
|
||||
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads reference</a>
|
||||
for details.</p>
|
||||
<a name="default_arguments.init_and_optional"></a><h2>
|
||||
<a name="id424831"></a>init and optional</h2>
|
||||
<a name="id456586"></a>init and optional</h2>
|
||||
<p>
|
||||
A similar facility is provided for class constructors, again, with
|
||||
default arguments or a sequence of overloads. Remember <tt class="literal">init<...></tt>? For example,
|
||||
@@ -416,11 +404,8 @@ Notice the use of <tt class="literal">init<...></tt> and <tt class="litera
|
||||
(optional arguments).</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||
<p>
|
||||
It was mentioned in passing in the previous section that
|
||||
<tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
@@ -456,17 +441,17 @@ Then...</p>
|
||||
Notice though that we have a situation now where we have a minimum of zero
|
||||
(0) arguments and a maximum of 3 arguments.</p>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||
<a name="id425478"></a>Manual Wrapping</h2>
|
||||
<a name="id457233"></a>Manual Wrapping</h2>
|
||||
<p>
|
||||
It is important to emphasize however that <span class="bold"><b>the overloaded functions must
|
||||
have a common sequence of initial arguments</b></span>. Otherwise, our scheme above
|
||||
will not work. If this is not the case, we have to wrap our functions
|
||||
<a href="functions.html#overloading" target="_top">manually</a>.</p>
|
||||
<a href="functions.html#python.overloading" title="Overloading">manually</a>.</p>
|
||||
<p>
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> and
|
||||
its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following up on our example
|
||||
presented in the section <a href="functions.html#overloading" target="_top">on overloading</a>, since the
|
||||
presented in the section <a href="functions.html#python.overloading" title="Overloading">on overloading</a>, since the
|
||||
first 4 overload functins have a common sequence of initial arguments, we
|
||||
can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> to automatically wrap the
|
||||
first three of the <tt class="literal">def</tt>s and manually wrap just the last. Here's
|
||||
|
||||
@@ -3,33 +3,30 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Building Hello World</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.hello"></a> Building Hello World</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||
<a name="hello.from_start_to_finish"></a><h2>
|
||||
<a name="id343708"></a>From Start To Finish</h2>
|
||||
<a name="id446728"></a>From Start To Finish</h2>
|
||||
<p>
|
||||
Now the first thing you'd want to do is to build the Hello World module and
|
||||
try it for yourself in Python. In this section, we shall outline the steps
|
||||
@@ -95,10 +92,10 @@ minimalist <span class="emphasis"><em>bjam</em></span> script that builds the DL
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory or somewhere in your path such that <tt class="literal">bjam</tt> can be executed in
|
||||
the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.</p>
|
||||
<a name="hello.let_s_jam_"></a><h2>
|
||||
<a name="id343869"></a>Let's Jam!</h2>
|
||||
<a name="id377058"></a>Let's Jam!</h2>
|
||||
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
|
||||
<p>
|
||||
Here is our minimalist Jamfile:</p>
|
||||
@@ -131,7 +128,7 @@ Finally we declare our <tt class="literal">hello</tt> extension:</p>
|
||||
;
|
||||
</tt></pre>
|
||||
<a name="hello.running_bjam"></a><h2>
|
||||
<a name="id343964"></a>Running bjam</h2>
|
||||
<a name="id377153"></a>Running bjam</h2>
|
||||
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line interpreter.</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>Start it up.</p></blockquote></div>
|
||||
<p>
|
||||
|
||||
@@ -3,31 +3,28 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Iterators</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="embedding.html" title="Embedding">
|
||||
<link rel="prev" href="embedding.html" title="Embedding">
|
||||
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.iterators"></a>Iterators</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.iterators"></a>Iterators</h2></div></div></div>
|
||||
<p>
|
||||
In C++, and STL in particular, we see iterators everywhere. Python also has
|
||||
iterators, but these are two very different beasts.</p>
|
||||
|
||||
@@ -3,31 +3,28 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Object Interface</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="functions.html" title="Functions">
|
||||
<link rel="prev" href="functions.html" title="Functions">
|
||||
<link rel="next" href="embedding.html" title="Embedding">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.object"></a> Object Interface</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.object"></a> Object Interface</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="object.html#python.basic_interface">Basic Interface</a></span></dt>
|
||||
<dt><span class="section"><a href="object.html#python.derived_object_types">Derived Object types</a></span></dt>
|
||||
@@ -47,11 +44,8 @@ feel. Boost.Python C++ <tt class="literal">object</tt>s are as close as possible
|
||||
should minimize the learning curve significantly.</p>
|
||||
<p><span class="inlinemediaobject"><img src="../images/python.png"></span></p>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||
<p>
|
||||
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the intricacies of dealing with
|
||||
<tt class="literal">PyObject</tt>s such as managing reference counting are handled by the
|
||||
@@ -86,11 +80,8 @@ code in C++, the look and feel should be immediately apparent to the Python
|
||||
coder.</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python comes with a set of derived <tt class="literal">object</tt> types corresponding to
|
||||
that of Python's:</p>
|
||||
@@ -155,7 +146,7 @@ C++:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">dict</span><span class="identifier"> d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> #<span class="identifier"> copies</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="identifier">
|
||||
d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span><span class="special"> =</span><span class="number"> 3</span><span class="special">;</span> #<span class="identifier"> modifies</span><span class="identifier"> the</span><span class="identifier"> copy</span></tt></pre>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||
<a name="id427284"></a>class_<T> as objects</h2>
|
||||
<a name="id459043"></a>class_<T> as objects</h2>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt> may
|
||||
also be one of these types! The following code snippet wraps the class
|
||||
@@ -171,11 +162,8 @@ We can use this to create wrapped instances. Example:</p>
|
||||
assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span><span class="special"> ==</span><span class="number"> 5.0</span><span class="special">);</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||
<p>
|
||||
At some point, we will need to get C++ values out of object instances. This
|
||||
can be achieved with the <tt class="literal">extract<T></tt> function. Consider the following:</p>
|
||||
@@ -208,11 +196,8 @@ facility in fact solves the mutable copying problem:</p>
|
||||
d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span><span class="special"> =</span><span class="number"> 3</span><span class="special">;</span> #<span class="identifier"> modifies</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special"> !</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.enums"></a>Enums</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While
|
||||
Python has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums to
|
||||
|
||||
@@ -3,30 +3,27 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> General Techniques</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="previous" href="exception.html" title=" Exception Translation">
|
||||
<link rel="prev" href="exception.html" title=" Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../libraries.html">Libraries</a></td>
|
||||
<td align="center"><a href="../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.techniques"></a> General Techniques</h2></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.techniques"></a> General Techniques</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="techniques.html#python.creating_packages">Creating Packages</a></span></dt>
|
||||
<dt><span class="section"><a href="techniques.html#python.extending_wrapped_objects_in_python">Extending Wrapped Objects in Python</a></span></dt>
|
||||
@@ -35,11 +32,8 @@
|
||||
<p>
|
||||
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</p>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.creating_packages"></a>Creating Packages</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
|
||||
<p>
|
||||
A Python package is a collection of modules that provide to the user a certain
|
||||
functionality. If you're not familiar on how to create packages, a good
|
||||
@@ -108,7 +102,7 @@ actually a Python package. It can be a empty file, but can also perform some
|
||||
magic, that will be shown later.</p>
|
||||
<p>
|
||||
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt> into his
|
||||
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||
and fire up the interpreter:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
|
||||
>>></span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
||||
@@ -187,11 +181,8 @@ from the <tt class="literal">filters</tt> package:</p>
|
||||
>>></span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo_noise</span><span class="special">(...)</span></tt></pre>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
|
||||
<p>
|
||||
Thanks to Python's flexibility, you can easily add new methods to a class,
|
||||
even after it was already created:</p>
|
||||
@@ -221,7 +212,7 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
|
||||
}</span></tt></pre>
|
||||
<p>
|
||||
If we are using the technique from the previous session,
|
||||
<a href="techniques.html#creating_packages" target="_top">Creating Packages</a>, we can code directly
|
||||
<a href="techniques.html#python.creating_packages" title="Creating Packages">Creating Packages</a>, we can code directly
|
||||
into <tt class="literal">geom/<span class="underline">_init</span>_.py</tt>:</p>
|
||||
<pre class="programlisting"><tt class="literal"><span class="identifier">from</span><span class="identifier"> _geom</span><span class="identifier"> import</span><span class="special"> *</span>
|
||||
|
||||
@@ -289,11 +280,8 @@ with virtually zero memory footprint and zero compile-time overhead for
|
||||
the keyword support.</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage">
|
||||
<div><div><h3 class="title">
|
||||
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
|
||||
<p>
|
||||
If you have ever exported a lot of classes, you know that it takes quite a good
|
||||
time to compile the Boost.Python wrappers. Plus the memory consumption can
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
[/ QuickBook Document version 0.9 ]
|
||||
|
||||
[def __note__ [$../images/note.png]]
|
||||
[def __alert__ [$../images/alert.png]]
|
||||
[def __tip__ [$../images/tip.png]]
|
||||
[def :-) [$../images/smiley.png]]
|
||||
[def __note__ [$images/note.png]]
|
||||
[def __alert__ [$images/alert.png]]
|
||||
[def __tip__ [$images/tip.png]]
|
||||
[def :-) [$images/smiley.png]]
|
||||
|
||||
[section QuickStart]
|
||||
|
||||
@@ -86,7 +86,7 @@ with every boost distribution: [*bjam].
|
||||
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
hello world module and run it in Python. For a complete reference to
|
||||
building Boost.Python, check out: [@../../../../building.html building.html].
|
||||
building Boost.Python, check out: [@../../../building.html building.html].
|
||||
After this brief ['bjam] tutorial, we should have built two DLLs:
|
||||
|
||||
* boost_python.dll
|
||||
@@ -111,7 +111,7 @@ minimalist ['bjam] script that builds the DLLs for us.
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory or somewhere in your path such that [^bjam] can be executed in
|
||||
the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
[@http://sourceforge.net/project/showfiles.php?group_id=7586 here].
|
||||
|
||||
[h2 Let's Jam!]
|
||||
@@ -175,7 +175,7 @@ Python modules. Example:
|
||||
|
||||
The above assumes that the Python installation is in [^c:/dev/tools/python]
|
||||
and that we are using Python version 2.2. You'll have to tweak this path
|
||||
appropriately.
|
||||
appropriately.
|
||||
|
||||
[blurb __tip__ Be sure not to include a third number, e.g. [*not] "2.2.1",
|
||||
even if that's the version you have.]
|
||||
@@ -189,7 +189,7 @@ Finally:
|
||||
|
||||
We are again assuming that we are using Microsoft Visual C++ version 6. If
|
||||
not, then you will have to specify the appropriate tool. See
|
||||
[@../../../../../../../tools/build/index.html Building Boost Libraries] for
|
||||
[@../../../../../../tools/build/index.html Building Boost Libraries] for
|
||||
further details.
|
||||
|
||||
It should be building now:
|
||||
@@ -454,8 +454,11 @@ Now we can inform Boost.Python of the inheritance relationship between
|
||||
|
||||
Doing so, we get some things for free:
|
||||
|
||||
# Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
|
||||
# [*If] Base is polymorphic, [^Derived] objects which have been passed to Python via a pointer or reference to [^Base] can be passed where a pointer or reference to [^Derived] is expected.
|
||||
# Derived automatically inherits all of Base's Python methods
|
||||
(wrapped C++ member functions)
|
||||
# [*If] Base is polymorphic, [^Derived] objects which have been passed to
|
||||
Python via a pointer or reference to [^Base] can be passed where a pointer
|
||||
or reference to [^Derived] is expected.
|
||||
|
||||
Now, we shall expose the C++ free functions [^b] and [^d] and [^factory]:
|
||||
|
||||
@@ -468,155 +471,80 @@ instances of class [^Derived]. In such cases, we use
|
||||
[^return_value_policy<manage_new_object>] to instruct Python to adopt
|
||||
the pointer to [^Base] and hold the instance in a new Python [^Base]
|
||||
object until the the Python object is destroyed. We shall see more of
|
||||
Boost.Python [@functions.html#python.call_policies call policies] later.
|
||||
Boost.Python [link python.call_policies call policies] later.
|
||||
|
||||
// Tell Python to take ownership of factory's result
|
||||
def("factory", factory,
|
||||
return_value_policy<manage_new_object>());
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Class Virtual Functions]
|
||||
|
||||
In this section, we shall learn how to make functions behave
|
||||
polymorphically through virtual functions. Continuing our example, let us
|
||||
add a virtual function to our [^Base] class:
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our [^Base] class:
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual int f() = 0;
|
||||
};
|
||||
|
||||
Since [^f] is a pure virtual function, [^Base] is now an abstract
|
||||
class. Given an instance of our class, the free function [^call_f]
|
||||
calls some implementation of this virtual function in a concrete
|
||||
derived class:
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||
design. In principle, it should be possible to expose the interface for a 3rd
|
||||
party library without changing it. It is not ideal to add anything to our class
|
||||
`Base`. Yet, when you have a virtual function that's going to be overridden in
|
||||
Python and called polymorphically *from C++*, we'll need to add some
|
||||
scaffoldings to make things work properly. What we'll do is write a class
|
||||
wrapper that derives from `Base` that will unintrusively hook into the virtual
|
||||
functions so that a Python override may be called:
|
||||
|
||||
int call_f(Base& b) { return b.f(); }
|
||||
|
||||
To allow this function to be implemented in a Python derived class, we
|
||||
need to create a class wrapper:
|
||||
|
||||
struct BaseWrap : Base
|
||||
struct BaseWrap : Base, wrapper<Base>
|
||||
{
|
||||
BaseWrap(PyObject* self_)
|
||||
: self(self_) {}
|
||||
int f() { return call_method<int>(self, "f"); }
|
||||
PyObject* self;
|
||||
int f()
|
||||
{
|
||||
return this->get_override("f")();
|
||||
}
|
||||
};
|
||||
|
||||
Notice too that in addition to inheriting from `Base`, we also multiply-
|
||||
inherited `wrapper<Base>` (See [@../../../v2/wrapper.html Wrapper]). The
|
||||
`wrapper` template makes the job of wrapping classes that are meant to
|
||||
overridden in Python, easier.
|
||||
|
||||
struct BaseWrap : Base
|
||||
{
|
||||
BaseWrap(PyObject* self_)
|
||||
: self(self_) {}
|
||||
BaseWrap(PyObject* self_, Base const& copy)
|
||||
: Base(copy), self(self_) {}
|
||||
int f() { return call_method<int>(self, "f"); }
|
||||
int default_f() { return Base::f(); } // <<=== ***ADDED***
|
||||
PyObject* self;
|
||||
};
|
||||
[blurb __alert__ MSVC6/7 Workaround\n\n
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:\n\n
|
||||
`return call<int>(this->get_override("f").ptr());`.]
|
||||
|
||||
BaseWrap's overridden virtual member function `f` in effect calls the
|
||||
corresponding method of the Python object through `get_override`.
|
||||
|
||||
Finally, exposing `Base`:
|
||||
|
||||
class_<BaseWrap, boost::noncopyable>("Base")
|
||||
.def("f", pure_virtual(&Base::f))
|
||||
;
|
||||
|
||||
`pure_virtual` signals Boost.Python that the function `f` is a pure virtual
|
||||
function.
|
||||
|
||||
[blurb __note__ [*member function and methods]\n\n Python, like
|
||||
many object oriented languages uses the term [*methods]. Methods
|
||||
correspond roughly to C++'s [*member functions]]
|
||||
|
||||
Our class wrapper [^BaseWrap] is derived from [^Base]. Its overridden
|
||||
virtual member function [^f] in effect calls the corresponding method
|
||||
of the Python object [^self], which is a pointer back to the Python
|
||||
[^Base] object holding our [^BaseWrap] instance.
|
||||
|
||||
[blurb __note__ [*Why do we need BaseWrap?]\n\n]
|
||||
|
||||
['You may ask], "Why do we need the [^BaseWrap] derived class? This could
|
||||
have been designed so that everything gets done right inside of
|
||||
Base."\n\n
|
||||
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an
|
||||
existing C++ design. In principle, it should be possible to expose the
|
||||
interface for a 3rd party library without changing it. To unintrusively
|
||||
hook into the virtual functions so that a Python override may be called, we
|
||||
must use a derived class.\n\n
|
||||
|
||||
Note however that you don't need to do this to get methods overridden
|
||||
in Python to behave virtually when called ['from] [*Python]. The only
|
||||
time you need to do the [^BaseWrap] dance is when you have a virtual
|
||||
function that's going to be overridden in Python and called
|
||||
polymorphically ['from] [*C++].]
|
||||
|
||||
Wrapping [^Base] and the free function [^call_f]:
|
||||
|
||||
class_<Base, BaseWrap, boost::noncopyable>("Base", no_init)
|
||||
;
|
||||
def("call_f", call_f);
|
||||
|
||||
Notice that we parameterized the [^class_] template with [^BaseWrap] as the
|
||||
second parameter. What is [^noncopyable]? Without it, the library will try
|
||||
to create code for converting Base return values of wrapped functions to
|
||||
Python. To do that, it needs Base's copy constructor... which isn't
|
||||
available, since Base is an abstract class.
|
||||
|
||||
In Python, let us try to instantiate our [^Base] class:
|
||||
|
||||
>>> base = Base()
|
||||
RuntimeError: This class cannot be instantiated from Python
|
||||
|
||||
Why is it an error? [^Base] is an abstract class. As such it is advisable
|
||||
to define the Python wrapper with [^no_init] as we have done above. Doing
|
||||
so will disallow abstract base classes such as [^Base] to be instantiated.
|
||||
|
||||
[endsect]
|
||||
[section Deriving a Python Class]
|
||||
|
||||
Continuing, we can derive from our base class Base in Python and override
|
||||
the virtual function in Python. Before we can do that, we have to set up
|
||||
our [^class_] wrapper as:
|
||||
|
||||
class_<Base, BaseWrap, boost::noncopyable>("Base")
|
||||
;
|
||||
|
||||
Otherwise, we have to suppress the Base class' [^no_init] by adding an
|
||||
[^__init__()] method to all our derived classes. [^no_init] actually adds
|
||||
an [^__init__] method that raises a Python RuntimeError exception.
|
||||
|
||||
>>> class Derived(Base):
|
||||
... def f(self):
|
||||
... return 42
|
||||
...
|
||||
|
||||
Cool eh? A Python class deriving from a C++ class!
|
||||
|
||||
Let's now make an instance of our Python class [^Derived]:
|
||||
|
||||
>>> derived = Derived()
|
||||
|
||||
Calling [^derived.f()]:
|
||||
|
||||
>>> derived.f()
|
||||
42
|
||||
|
||||
Will yield the expected result. Finally, calling calling the free function
|
||||
[^call_f] with [^derived] as argument:
|
||||
|
||||
>>> call_f(derived)
|
||||
42
|
||||
|
||||
Will also yield the expected result.
|
||||
|
||||
Here's what's happening:
|
||||
|
||||
# [^call_f(derived)] is called in Python
|
||||
# This corresponds to [^def("call_f", call_f);]. Boost.Python dispatches this call.
|
||||
# [^int call_f(Base& b) { return b.f(); }] accepts the call.
|
||||
# The overridden virtual function [^f] of [^BaseWrap] is called.
|
||||
# [^call_method<int>(self, "f");] dispatches the call back to Python.
|
||||
# [^def f(self): return 42] is finally called.
|
||||
|
||||
[endsect]
|
||||
[section Virtual Functions with Default Implementations]
|
||||
|
||||
Recall that in the [@exposing.html#class_virtual_functions previous section], we
|
||||
wrapped a class with a pure virtual function that we then implemented in
|
||||
C++ or Python classes derived from it. Our base class:
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
wrapped using Boost.Python's [@../../../v2//wrapper.html class wrapper]
|
||||
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
|
||||
mechanism is a bit different.
|
||||
|
||||
Recall that in the [link python.class_virtual_functions previous section], we
|
||||
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||
Python classes derived from it. Our base class:
|
||||
|
||||
struct Base
|
||||
{
|
||||
@@ -628,33 +556,42 @@ not declared as pure virtual:
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual int f() { return 0; }
|
||||
};
|
||||
|
||||
and instead had a default implementation that returns [^0], as shown above,
|
||||
we need to add a forwarding function that calls the [^Base] default virtual
|
||||
function [^f] implementation:
|
||||
|
||||
struct BaseWrap : Base
|
||||
We wrap it this way:
|
||||
|
||||
struct BaseWrap : Base, wrapper<Base>
|
||||
{
|
||||
BaseWrap(PyObject* self_)
|
||||
: self(self_) {}
|
||||
int f() { return call_method<int>(self, "f"); }
|
||||
int default_f() { return Base::f(); } // <<=== ***ADDED***
|
||||
PyObject* self;
|
||||
int f()
|
||||
{
|
||||
if (override f = this->get_override("f"))
|
||||
return f(); // *note*
|
||||
return Base::f();
|
||||
}
|
||||
|
||||
int default_f() { return this->Base::f(); }
|
||||
};
|
||||
|
||||
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
|
||||
override for `f`. If none, then we call `Base::f()`.
|
||||
|
||||
Then, Boost.Python needs to keep track of 1) the dispatch function [^f] and
|
||||
2) the forwarding function to its default implementation [^default_f].
|
||||
There's a special [^def] function for this purpose. Here's how it is
|
||||
applied to our example above:
|
||||
[blurb __alert__ MSVC6/7 Workaround\n\n
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
|
||||
with the `*note*` as:\n\n
|
||||
`return call<char const*>(f.ptr());`.]
|
||||
|
||||
class_<Base, BaseWrap, BaseWrap, boost::noncopyable>("Base")
|
||||
Finally, exposing:
|
||||
|
||||
class_<BaseWrap, boost::noncopyable>("Base")
|
||||
.def("f", &Base::f, &BaseWrap::default_f)
|
||||
;
|
||||
|
||||
Note that we are allowing [^Base] objects to be instantiated this time,
|
||||
unlike before where we specifically defined the [^class_<Base>] with
|
||||
[^no_init].
|
||||
Take note that we expose both `&Base::f` and `&BaseWrap::default_f`.
|
||||
Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the
|
||||
forwarding function to its default implementation [^default_f]. There's a
|
||||
special [^def] function for this purpose.
|
||||
|
||||
In Python, the results would be as expected:
|
||||
|
||||
@@ -675,16 +612,6 @@ Calling [^derived.f()]:
|
||||
>>> derived.f()
|
||||
42
|
||||
|
||||
Calling [^call_f], passing in a [^base] object:
|
||||
|
||||
>>> call_f(base)
|
||||
0
|
||||
|
||||
Calling [^call_f], passing in a [^derived] object:
|
||||
|
||||
>>> call_f(derived)
|
||||
42
|
||||
|
||||
[endsect]
|
||||
[section Class Operators/Special Functions]
|
||||
|
||||
@@ -918,7 +845,7 @@ or more policies can be composed by chaining. Here's the general syntax:
|
||||
policy3<args...> > >
|
||||
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found [@../../../../v2/reference.html#models_of_call_policies here].
|
||||
these can be found [@../../../v2/reference.html#models_of_call_policies here].
|
||||
|
||||
* [*with_custodian_and_ward]\n Ties lifetimes of the arguments
|
||||
* [*with_custodian_and_ward_postcall]\n Ties lifetimes of the arguments and results
|
||||
@@ -1000,7 +927,7 @@ to retrieve the default arguments:
|
||||
def("f", f); // defaults lost!
|
||||
|
||||
Because of this, when wrapping C++ code, we had to resort to manual
|
||||
wrapping as outlined in the [@functions.html#overloading previous section], or
|
||||
wrapping as outlined in the [link python.overloading previous section], or
|
||||
writing thin wrappers:
|
||||
|
||||
// write "thin wrappers"
|
||||
@@ -1073,7 +1000,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
|
||||
|
||||
.def("wack_em", &george::wack_em, george_overloads());
|
||||
|
||||
See the [@../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
|
||||
See the [@../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
|
||||
for details.
|
||||
|
||||
[h2 init and optional]
|
||||
@@ -1140,12 +1067,12 @@ Notice though that we have a situation now where we have a minimum of zero
|
||||
It is important to emphasize however that [*the overloaded functions must
|
||||
have a common sequence of initial arguments]. Otherwise, our scheme above
|
||||
will not work. If this is not the case, we have to wrap our functions
|
||||
[@functions.html#overloading manually].
|
||||
[link python.overloading manually].
|
||||
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] and
|
||||
its sister, [^BOOST_PYTHON_FUNCTION_OVERLOADS]. Following up on our example
|
||||
presented in the section [@functions.html#overloading on overloading], since the
|
||||
presented in the section [link python.overloading on overloading], since the
|
||||
first 4 overload functins have a common sequence of initial arguments, we
|
||||
can use [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] to automatically wrap the
|
||||
first three of the [^def]s and manually wrap just the last. Here's
|
||||
@@ -1179,7 +1106,7 @@ bidirectional mapping between C++ and Python while maintaining the Python
|
||||
feel. Boost.Python C++ [^object]s are as close as possible to Python. This
|
||||
should minimize the learning curve significantly.
|
||||
|
||||
[$../images/python.png]
|
||||
[$images/python.png]
|
||||
|
||||
[section Basic Interface]
|
||||
|
||||
@@ -1361,7 +1288,7 @@ associated with the C++ type passed as its first parameter.
|
||||
[blurb __note__ [*what is a scope?]\n\n The scope is a class that has an
|
||||
associated global Python object which controls the Python namespace in
|
||||
which new extension classes and wrapped functions will be defined as
|
||||
attributes. Details can be found [@../../../../v2/scope.html here].]
|
||||
attributes. Details can be found [@../../../v2/scope.html here].]
|
||||
|
||||
You can access those values in Python as
|
||||
|
||||
@@ -1422,8 +1349,8 @@ Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
|
||||
variants are called [^boost_python.lib] (for release builds) and
|
||||
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See [@../../../../building.html
|
||||
Building and Testing] on how to do this.
|
||||
you probably haven't built Boost.Python yet. See
|
||||
[@../../../building.html Building and Testing] on how to do this.
|
||||
|
||||
Python's static link library can be found in the [^/libs] subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
@@ -1477,8 +1404,8 @@ There is a difference however. While the reference-counting is fully
|
||||
automatic in Python, the Python/C API requires you to do it
|
||||
[@http://www.python.org/doc/current/api/refcounts.html by hand]. This is
|
||||
messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the [@../../v2/handle.html handle] and
|
||||
[@../../../../v2/object.html object] class templates to automate the process.
|
||||
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
|
||||
[@../../../v2/object.html object] class templates to automate the process.
|
||||
|
||||
[h2 Reference-counting handles and objects]
|
||||
|
||||
@@ -1490,7 +1417,7 @@ be 'handled' by Boost.Python.
|
||||
|
||||
For a function returning a ['borrowed reference] we'll have to tell the
|
||||
[^handle] that the [^PyObject*] is borrowed with the aptly named
|
||||
[@../../../../v2/handle.html#borrowed-spec borrowed] function. Two functions
|
||||
[@../../../v2/handle.html#borrowed-spec borrowed] function. Two functions
|
||||
returning borrowed references are PyImport_AddModule and PyModule_GetDict.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
@@ -1622,10 +1549,10 @@ perform.
|
||||
|
||||
[h2 Exception handling]
|
||||
|
||||
If an exception occurs in the execution of some Python code, the PyRun_String
|
||||
function returns a null pointer. Constructing a [^handle] out of this null
|
||||
pointer throws [@../../../../v2/errors.html#error_already_set-spec error_already_set],
|
||||
so basically, the Python exception is automatically translated into a
|
||||
If an exception occurs in the execution of some Python code, the PyRun_String
|
||||
function returns a null pointer. Constructing a [^handle] out of this null
|
||||
pointer throws [@../../../v2/errors.html#error_already_set-spec error_already_set],
|
||||
so basically, the Python exception is automatically translated into a
|
||||
C++ exception when using [^handle]:
|
||||
|
||||
try
|
||||
@@ -1645,13 +1572,13 @@ C++ exception when using [^handle]:
|
||||
// handle the exception in some way
|
||||
}
|
||||
|
||||
The [^error_already_set] exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
[@http://www.python.org/doc/api/exceptionHandling.html exception handling functions]
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
[@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the [@http://www.python.org/doc/api/standardExceptions.html
|
||||
The [^error_already_set] exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
[@http://www.python.org/doc/api/exceptionHandling.html exception handling functions]
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
[@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the [@http://www.python.org/doc/api/standardExceptions.html
|
||||
standard exceptions]:
|
||||
|
||||
catch(error_already_set)
|
||||
@@ -1667,11 +1594,11 @@ standard exceptions]:
|
||||
}
|
||||
}
|
||||
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
|
||||
|
||||
If you'd rather not have [^handle] throw a C++ exception when it is constructed, you
|
||||
can use the [@../../v2/handle.html#allow_null-spec allow_null] function in the same
|
||||
If you'd rather not have [^handle] throw a C++ exception when it is constructed, you
|
||||
can use the [@../../../v2/handle.html#allow_null-spec allow_null] function in the same
|
||||
way you'd use borrowed:
|
||||
|
||||
handle<> result((allow_null(PyRun_String(
|
||||
@@ -1859,7 +1786,7 @@ actually a Python package. It can be a empty file, but can also perform some
|
||||
magic, that will be shown later.
|
||||
|
||||
Now our package is ready. All the user has to do is put [^sounds] into his
|
||||
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH]
|
||||
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH]
|
||||
and fire up the interpreter:
|
||||
|
||||
>>> import sounds.io
|
||||
@@ -1980,7 +1907,7 @@ we have a class [^point] in C++:
|
||||
}
|
||||
|
||||
If we are using the technique from the previous session,
|
||||
[@techniques.html#creating_packages Creating Packages], we can code directly
|
||||
[link python.creating_packages Creating Packages], we can code directly
|
||||
into [^geom/__init__.py]:
|
||||
|
||||
from _geom import *
|
||||
@@ -2099,13 +2026,13 @@ This method is recommended too if you are developing the C++ library and
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.
|
||||
|
||||
[blurb __note__ If you're exporting your classes with [@../../../../../pyste/index.html Pyste],
|
||||
[blurb __note__ If you're exporting your classes with [@../../../../pyste/index.html Pyste],
|
||||
take a look at the [^--multiple] option, that generates the wrappers in
|
||||
various files as demonstrated here.]
|
||||
|
||||
[blurb __note__ This method is useful too if you are getting the error message
|
||||
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
|
||||
a large source file, as explained in the [@../../../../v2/faq.html#c1204 FAQ].]
|
||||
a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].]
|
||||
|
||||
[endsect]
|
||||
[endsect] [/ General Techniques]
|
||||
|
||||
@@ -108,7 +108,7 @@ with every boost distribution: <emphasis role="bold">bjam</emphasis>.</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Building without bjam</emphasis><para/>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Building without bjam</emphasis><para/>
|
||||
<para/>
|
||||
|
||||
Besides bjam, there are of course other ways to get your module built.
|
||||
@@ -128,7 +128,7 @@ with every boost distribution: <emphasis role="bold">bjam</emphasis>.</para>
|
||||
<para>
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
hello world module and run it in Python. For a complete reference to
|
||||
building Boost.Python, check out: <ulink url="../../../../building.html">building.html</ulink>.
|
||||
building Boost.Python, check out: <ulink url="../../../building.html">building.html</ulink>.
|
||||
After this brief <emphasis>bjam</emphasis> tutorial, we should have built two DLLs:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
@@ -162,7 +162,7 @@ minimalist <emphasis>bjam</emphasis> script that builds the DLLs for us.</para>
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory or somewhere in your path such that <literal>bjam</literal> can be executed in
|
||||
the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
platforms. The complete list of Bjam executables can be found
|
||||
<ulink url="http://sourceforge.net/project/showfiles.php?group_id=7586">here</ulink>.</para>
|
||||
<anchor id="hello.let_s_jam_" /><bridgehead renderas="sect2">Let's Jam!</bridgehead><para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/jam.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
@@ -222,7 +222,7 @@ appropriately.</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/tip.png"></imagedata></imageobject></inlinemediaobject> Be sure not to include a third number, e.g. <emphasis role="bold">not</emphasis> "2.2.1",
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/tip.png"></imagedata></imageobject></inlinemediaobject> Be sure not to include a third number, e.g. <emphasis role="bold">not</emphasis> "2.2.1",
|
||||
even if that's the version you have.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
@@ -241,7 +241,7 @@ Finally:</para>
|
||||
<para>
|
||||
We are again assuming that we are using Microsoft Visual C++ version 6. If
|
||||
not, then you will have to specify the appropriate tool. See
|
||||
<ulink url="../../../../../../../tools/build/index.html">Building Boost Libraries</ulink> for
|
||||
<ulink url="../../../../../../tools/build/index.html">Building Boost Libraries</ulink> for
|
||||
further details.</para>
|
||||
<para>
|
||||
It should be building now:</para>
|
||||
@@ -563,9 +563,12 @@ Now we can inform Boost.Python of the inheritance relationship between
|
||||
Doing so, we get some things for free:</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
|
||||
Derived automatically inherits all of Base's Python methods
|
||||
(wrapped C++ member functions)
|
||||
</listitem><listitem>
|
||||
<emphasis role="bold">If</emphasis> Base is polymorphic, <literal>Derived</literal> objects which have been passed to Python via a pointer or reference to <literal>Base</literal> can be passed where a pointer or reference to <literal>Derived</literal> is expected.
|
||||
<emphasis role="bold">If</emphasis> Base is polymorphic, <literal>Derived</literal> objects which have been passed to
|
||||
Python via a pointer or reference to <literal>Base</literal> can be passed where a pointer
|
||||
or reference to <literal>Derived</literal> is expected.
|
||||
</listitem>
|
||||
</orderedlist><para>
|
||||
Now, we shall expose the C++ free functions <literal>b</literal> and <literal>d</literal> and <literal>factory</literal>:</para>
|
||||
@@ -582,7 +585,7 @@ instances of class <literal>Derived</literal>. In such cases, we use
|
||||
<literal>return_value_policy<manage_new_object></literal> to instruct Python to adopt
|
||||
the pointer to <literal>Base</literal> and hold the instance in a new Python <literal>Base</literal>
|
||||
object until the the Python object is destroyed. We shall see more of
|
||||
Boost.Python <ulink url="functions.html#python.call_policies">call policies</ulink> later.</para>
|
||||
Boost.Python <link linkend="python.call_policies">call policies</link> later.</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="comment">// Tell Python to take ownership of factory's result
|
||||
@@ -594,60 +597,82 @@ Boost.Python <ulink url="functions.html#python.call_policies">call policies</uli
|
||||
<section id="python.class_virtual_functions">
|
||||
<title>Class Virtual Functions</title>
|
||||
<para>
|
||||
In this section, we shall learn how to make functions behave
|
||||
polymorphically through virtual functions. Continuing our example, let us
|
||||
add a virtual function to our <literal>Base</literal> class:</para>
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our <literal>Base</literal> class:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
virtual</phrase><phrase role="special"> ~</phrase><phrase role="identifier">Base</phrase><phrase role="special">()</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
|
||||
virtual</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> =</phrase><phrase role="number"> 0</phrase><phrase role="special">;</phrase><phrase role="special">
|
||||
};</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Since <literal>f</literal> is a pure virtual function, <literal>Base</literal> is now an abstract
|
||||
class. Given an instance of our class, the free function <literal>call_f</literal>
|
||||
calls some implementation of this virtual function in a concrete
|
||||
derived class:</para>
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||
design. In principle, it should be possible to expose the interface for a 3rd
|
||||
party library without changing it. It is not ideal to add anything to our class
|
||||
<code><phrase role="identifier">Base</phrase></code>. Yet, when you have a virtual function that's going to be overridden in
|
||||
Python and called polymorphically <emphasis role="bold">from C++</emphasis>, we'll need to add some
|
||||
scaffoldings to make things work properly. What we'll do is write a class
|
||||
wrapper that derives from <code><phrase role="identifier">Base</phrase></code> that will unintrusively hook into the virtual
|
||||
functions so that a Python override may be called:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">int</phrase><phrase role="identifier"> call_f</phrase><phrase role="special">(</phrase><phrase role="identifier">Base</phrase><phrase role="special">&</phrase><phrase role="identifier"> b</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> b</phrase><phrase role="special">.</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
To allow this function to be implemented in a Python derived class, we
|
||||
need to create a class wrapper:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
{</phrase><phrase role="identifier">
|
||||
BaseWrap</phrase><phrase role="special">(</phrase><phrase role="identifier">PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self_</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
:</phrase><phrase role="identifier"> self</phrase><phrase role="special">(</phrase><phrase role="identifier">self_</phrase><phrase role="special">)</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> call_method</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">>(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="string"> "f"</phrase><phrase role="special">);</phrase><phrase role="special"> }</phrase><phrase role="identifier">
|
||||
PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self</phrase><phrase role="special">;</phrase><phrase role="special">
|
||||
};</phrase><phrase role="keyword">
|
||||
|
||||
|
||||
struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
{</phrase><phrase role="identifier">
|
||||
BaseWrap</phrase><phrase role="special">(</phrase><phrase role="identifier">PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self_</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
:</phrase><phrase role="identifier"> self</phrase><phrase role="special">(</phrase><phrase role="identifier">self_</phrase><phrase role="special">)</phrase><phrase role="special"> {}</phrase><phrase role="identifier">
|
||||
BaseWrap</phrase><phrase role="special">(</phrase><phrase role="identifier">PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self_</phrase><phrase role="special">,</phrase><phrase role="identifier"> Base</phrase><phrase role="keyword"> const</phrase><phrase role="special">&</phrase><phrase role="identifier"> copy</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
:</phrase><phrase role="identifier"> Base</phrase><phrase role="special">(</phrase><phrase role="identifier">copy</phrase><phrase role="special">),</phrase><phrase role="identifier"> self</phrase><phrase role="special">(</phrase><phrase role="identifier">self_</phrase><phrase role="special">)</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> call_method</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">>(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="string"> "f"</phrase><phrase role="special">);</phrase><phrase role="special"> }</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> default_f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase><phrase role="comment"> // <<=== ***ADDED***
|
||||
</phrase><phrase role="identifier"> PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self</phrase><phrase role="special">;</phrase><phrase role="special">
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> wrapper</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">></phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
return</phrase><phrase role="keyword"> this</phrase><phrase role="special">-></phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">)();</phrase><phrase role="special">
|
||||
}</phrase><phrase role="special">
|
||||
};</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Notice too that in addition to inheriting from <code><phrase role="identifier">Base</phrase></code>, we also multiply-
|
||||
inherited <code><phrase role="identifier">wrapper</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">></phrase></code> (See <ulink url="../../../v2/wrapper.html">Wrapper</ulink>). The
|
||||
<code><phrase role="identifier">wrapper</phrase></code> template makes the job of wrapping classes that are meant to
|
||||
overridden in Python, easier.</para>
|
||||
<informaltable frame="all">
|
||||
<?dbhtml table-width="74%" ?>
|
||||
<tgroup cols="1">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">member function and methods</emphasis><para/>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> MSVC6/7 Workaround<para/>
|
||||
<para/>
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write <code><phrase role="identifier">f</phrase></code> as:<para/>
|
||||
<para/>
|
||||
|
||||
<code><phrase role="keyword">return</phrase><phrase role="identifier"> call</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">>(</phrase><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">).</phrase><phrase role="identifier">ptr</phrase><phrase role="special">());</phrase></code>.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para>
|
||||
BaseWrap's overridden virtual member function <code><phrase role="identifier">f</phrase></code> in effect calls the
|
||||
corresponding method of the Python object through <code><phrase role="identifier">get_override</phrase></code>.</para>
|
||||
<para>
|
||||
Finally, exposing <code><phrase role="identifier">Base</phrase></code>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="identifier">class_</phrase><phrase role="special"><</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">>(</phrase><phrase role="string">"Base"</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">,</phrase><phrase role="identifier"> pure_virtual</phrase><phrase role="special">(&</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">))</phrase><phrase role="special">
|
||||
;</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
<code><phrase role="identifier">pure_virtual</phrase></code> signals Boost.Python that the function <code><phrase role="identifier">f</phrase></code> is a pure virtual
|
||||
function.</para>
|
||||
<informaltable frame="all">
|
||||
<?dbhtml table-width="74%" ?>
|
||||
<tgroup cols="1">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">member function and methods</emphasis><para/>
|
||||
<para/>
|
||||
Python, like
|
||||
many object oriented languages uses the term <emphasis role="bold">methods</emphasis>. Methods
|
||||
@@ -656,147 +681,18 @@ correspond roughly to C++'s <emphasis role="bold">member functions</emphasis></e
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para>
|
||||
Our class wrapper <literal>BaseWrap</literal> is derived from <literal>Base</literal>. Its overridden
|
||||
virtual member function <literal>f</literal> in effect calls the corresponding method
|
||||
of the Python object <literal>self</literal>, which is a pointer back to the Python
|
||||
<literal>Base</literal> object holding our <literal>BaseWrap</literal> instance.</para>
|
||||
<informaltable frame="all">
|
||||
<?dbhtml table-width="74%" ?>
|
||||
<tgroup cols="1">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Why do we need BaseWrap?</emphasis><para/>
|
||||
<para/>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para>
|
||||
<emphasis>You may ask</emphasis>, "Why do we need the <literal>BaseWrap</literal> derived class? This could
|
||||
have been designed so that everything gets done right inside of
|
||||
Base."<para/>
|
||||
<para/>
|
||||
</para>
|
||||
<para>
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an
|
||||
existing C++ design. In principle, it should be possible to expose the
|
||||
interface for a 3rd party library without changing it. To unintrusively
|
||||
hook into the virtual functions so that a Python override may be called, we
|
||||
must use a derived class.<para/>
|
||||
<para/>
|
||||
</para>
|
||||
<para>
|
||||
Note however that you don't need to do this to get methods overridden
|
||||
in Python to behave virtually when called <emphasis>from</emphasis> <emphasis role="bold">Python</emphasis>. The only
|
||||
time you need to do the <literal>BaseWrap</literal> dance is when you have a virtual
|
||||
function that's going to be overridden in Python and called
|
||||
polymorphically <emphasis>from</emphasis> <emphasis role="bold">C++</emphasis>.]</para>
|
||||
<para>
|
||||
Wrapping <literal>Base</literal> and the free function <literal>call_f</literal>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="identifier">class_</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">>(</phrase><phrase role="string">"Base"</phrase><phrase role="special">,</phrase><phrase role="identifier"> no_init</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
;</phrase><phrase role="identifier">
|
||||
def</phrase><phrase role="special">(</phrase><phrase role="string">"call_f"</phrase><phrase role="special">,</phrase><phrase role="identifier"> call_f</phrase><phrase role="special">);</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Notice that we parameterized the <literal>class_</literal> template with <literal>BaseWrap</literal> as the
|
||||
second parameter. What is <literal>noncopyable</literal>? Without it, the library will try
|
||||
to create code for converting Base return values of wrapped functions to
|
||||
Python. To do that, it needs Base's copy constructor... which isn't
|
||||
available, since Base is an abstract class.</para>
|
||||
<para>
|
||||
In Python, let us try to instantiate our <literal>Base</literal> class:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> base</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Base</phrase><phrase role="special">()</phrase><phrase role="identifier">
|
||||
RuntimeError</phrase><phrase role="special">:</phrase><phrase role="identifier"> This</phrase><phrase role="keyword"> class</phrase><phrase role="identifier"> cannot</phrase><phrase role="identifier"> be</phrase><phrase role="identifier"> instantiated</phrase><phrase role="identifier"> from</phrase><phrase role="identifier"> Python</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Why is it an error? <literal>Base</literal> is an abstract class. As such it is advisable
|
||||
to define the Python wrapper with <literal>no_init</literal> as we have done above. Doing
|
||||
so will disallow abstract base classes such as <literal>Base</literal> to be instantiated.</para>
|
||||
</section>
|
||||
<section id="python.deriving_a_python_class">
|
||||
<title>Deriving a Python Class</title>
|
||||
<para>
|
||||
Continuing, we can derive from our base class Base in Python and override
|
||||
the virtual function in Python. Before we can do that, we have to set up
|
||||
our <literal>class_</literal> wrapper as:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="identifier">class_</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">>(</phrase><phrase role="string">"Base"</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
;</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Otherwise, we have to suppress the Base class' <literal>no_init</literal> by adding an
|
||||
<literal><emphasis role="underline">_init</emphasis>_()</literal> method to all our derived classes. <literal>no_init</literal> actually adds
|
||||
an <literal><emphasis role="underline">_init</emphasis>_</literal> method that raises a Python RuntimeError exception.</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="keyword"> class</phrase><phrase role="identifier"> Derived</phrase><phrase role="special">(</phrase><phrase role="identifier">Base</phrase><phrase role="special">):</phrase><phrase role="special">
|
||||
...</phrase><phrase role="identifier"> def</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="special">
|
||||
...</phrase><phrase role="keyword"> return</phrase><phrase role="number"> 42</phrase><phrase role="special">
|
||||
...</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Cool eh? A Python class deriving from a C++ class!</para>
|
||||
<para>
|
||||
Let's now make an instance of our Python class <literal>Derived</literal>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> derived</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Derived</phrase><phrase role="special">()</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Calling <literal>derived.f()</literal>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> derived</phrase><phrase role="special">.</phrase><phrase role="identifier">f</phrase><phrase role="special">()</phrase><phrase role="number">
|
||||
42</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Will yield the expected result. Finally, calling calling the free function
|
||||
<literal>call_f</literal> with <literal>derived</literal> as argument:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> call_f</phrase><phrase role="special">(</phrase><phrase role="identifier">derived</phrase><phrase role="special">)</phrase><phrase role="number">
|
||||
42</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Will also yield the expected result.</para>
|
||||
<para>
|
||||
Here's what's happening:</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<literal>call_f(derived)</literal> is called in Python
|
||||
</listitem><listitem>
|
||||
This corresponds to <literal>def("call_f", call_f);</literal>. Boost.Python dispatches this call.
|
||||
</listitem><listitem>
|
||||
<literal>int call_f(Base& b) { return b.f(); }</literal> accepts the call.
|
||||
</listitem><listitem>
|
||||
The overridden virtual function <literal>f</literal> of <literal>BaseWrap</literal> is called.
|
||||
</listitem><listitem>
|
||||
<literal>call_method<int>(self, "f");</literal> dispatches the call back to Python.
|
||||
</listitem><listitem>
|
||||
<literal>def f(self): return 42</literal> is finally called.
|
||||
</listitem>
|
||||
</orderedlist></section>
|
||||
<section id="python.virtual_functions_with_default_implementations">
|
||||
<title>Virtual Functions with Default Implementations</title>
|
||||
<para>
|
||||
Recall that in the <ulink url="exposing.html#class_virtual_functions">previous section</ulink>, we
|
||||
wrapped a class with a pure virtual function that we then implemented in
|
||||
C++ or Python classes derived from it. Our base class:</para>
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
wrapped using Boost.Python's <ulink url="../../../v2//wrapper.html">class wrapper</ulink>
|
||||
facilities. If we wish to wrap <emphasis role="bold">non</emphasis>-pure-virtual functions instead, the
|
||||
mechanism is a bit different.</para>
|
||||
<para>
|
||||
Recall that in the <link linkend="python.class_virtual_functions">previous section</link>, we
|
||||
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||
Python classes derived from it. Our base class:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
@@ -812,41 +708,63 @@ not declared as pure virtual:</para>
|
||||
<literal>
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
virtual</phrase><phrase role="special"> ~</phrase><phrase role="identifier">Base</phrase><phrase role="special">()</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
|
||||
virtual</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="number"> 0</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="special">
|
||||
};</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
and instead had a default implementation that returns <literal>0</literal>, as shown above,
|
||||
we need to add a forwarding function that calls the <literal>Base</literal> default virtual
|
||||
function <literal>f</literal> implementation:</para>
|
||||
We wrap it this way:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||
{</phrase><phrase role="identifier">
|
||||
BaseWrap</phrase><phrase role="special">(</phrase><phrase role="identifier">PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self_</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
:</phrase><phrase role="identifier"> self</phrase><phrase role="special">(</phrase><phrase role="identifier">self_</phrase><phrase role="special">)</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> call_method</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">>(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="string"> "f"</phrase><phrase role="special">);</phrase><phrase role="special"> }</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> default_f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase><phrase role="comment"> // <<=== ***ADDED***
|
||||
</phrase><phrase role="identifier"> PyObject</phrase><phrase role="special">*</phrase><phrase role="identifier"> self</phrase><phrase role="special">;</phrase><phrase role="special">
|
||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> wrapper</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">></phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special">
|
||||
{</phrase><phrase role="keyword">
|
||||
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">override</phrase><phrase role="identifier"> f</phrase><phrase role="special"> =</phrase><phrase role="keyword"> this</phrase><phrase role="special">-></phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">))</phrase><phrase role="keyword">
|
||||
return</phrase><phrase role="identifier"> f</phrase><phrase role="special">();</phrase><phrase role="comment"> // *note*
|
||||
</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special">
|
||||
}</phrase><phrase role="keyword">
|
||||
|
||||
int</phrase><phrase role="identifier"> default_f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="keyword"> this</phrase><phrase role="special">-></phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase><phrase role="special">
|
||||
};</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Then, Boost.Python needs to keep track of 1) the dispatch function <literal>f</literal> and
|
||||
2) the forwarding function to its default implementation <literal>default_f</literal>.
|
||||
There's a special <literal>def</literal> function for this purpose. Here's how it is
|
||||
applied to our example above:</para>
|
||||
Notice how we implemented <code><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase></code>. Now, we have to check if there is an
|
||||
override for <code><phrase role="identifier">f</phrase></code>. If none, then we call <code><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">()</phrase></code>.</para>
|
||||
<informaltable frame="all">
|
||||
<?dbhtml table-width="74%" ?>
|
||||
<tgroup cols="1">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> MSVC6/7 Workaround<para/>
|
||||
<para/>
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
|
||||
with the <code><phrase role="special">*</phrase><phrase role="identifier">note</phrase><phrase role="special">*</phrase></code> as:<para/>
|
||||
<para/>
|
||||
|
||||
<code><phrase role="keyword">return</phrase><phrase role="identifier"> call</phrase><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="keyword"> const</phrase><phrase role="special">*>(</phrase><phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">());</phrase></code>.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para>
|
||||
Finally, exposing:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="identifier">class_</phrase><phrase role="special"><</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">>(</phrase><phrase role="string">"Base"</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">,</phrase><phrase role="special"> &</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">,</phrase><phrase role="special"> &</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">default_f</phrase><phrase role="special">)</phrase>
|
||||
<phrase role="identifier">class_</phrase><phrase role="special"><</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">>(</phrase><phrase role="string">"Base"</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">"f"</phrase><phrase role="special">,</phrase><phrase role="special"> &</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">,</phrase><phrase role="special"> &</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">default_f</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
;</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Note that we are allowing <literal>Base</literal> objects to be instantiated this time,
|
||||
unlike before where we specifically defined the <literal>class_<Base></literal> with
|
||||
<literal>no_init</literal>.</para>
|
||||
Take note that we expose both <code><phrase role="special">&</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase></code> and <code><phrase role="special">&</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">default_f</phrase></code>.
|
||||
Boost.Python needs to keep track of 1) the dispatch function <literal>f</literal> and 2) the
|
||||
forwarding function to its default implementation <literal>default_f</literal>. There's a
|
||||
special <literal>def</literal> function for this purpose.</para>
|
||||
<para>
|
||||
In Python, the results would be as expected:</para>
|
||||
<programlisting>
|
||||
@@ -875,22 +793,6 @@ Calling <literal>derived.f()</literal>:</para>
|
||||
42</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Calling <literal>call_f</literal>, passing in a <literal>base</literal> object:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> call_f</phrase><phrase role="special">(</phrase><phrase role="identifier">base</phrase><phrase role="special">)</phrase><phrase role="number">
|
||||
0</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Calling <literal>call_f</literal>, passing in a <literal>derived</literal> object:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="special">>>></phrase><phrase role="identifier"> call_f</phrase><phrase role="special">(</phrase><phrase role="identifier">derived</phrase><phrase role="special">)</phrase><phrase role="number">
|
||||
42</phrase>
|
||||
</literal>
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="python.class_operators_special_functions">
|
||||
<title>Class Operators/Special Functions</title>
|
||||
@@ -966,7 +868,7 @@ Need we say more?</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> What is the business of <literal>operator<<</literal> <literal>.def(str(self))</literal>?
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> What is the business of <literal>operator<<</literal> <literal>.def(str(self))</literal>?
|
||||
Well, the method <literal>str</literal> requires the <literal>operator<<</literal> to do its work (i.e.
|
||||
<literal>operator<<</literal> is used by the method defined by def(str(self)).</entry>
|
||||
</row>
|
||||
@@ -1178,7 +1080,7 @@ or more policies can be composed by chaining. Here's the general syntax:</para>
|
||||
</programlisting>
|
||||
<para>
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found <ulink url="../../../../v2/reference.html#models_of_call_policies">here</ulink>.</para>
|
||||
these can be found <ulink url="../../../v2/reference.html#models_of_call_policies">here</ulink>.</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<emphasis role="bold">with_custodian_and_ward</emphasis><para/>
|
||||
@@ -1211,7 +1113,7 @@ Boost.Python v1 approach
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/smiley.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Remember the Zen, Luke:</emphasis><para/>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Remember the Zen, Luke:</emphasis><para/>
|
||||
<para/>
|
||||
|
||||
"Explicit is better than implicit"<para/>
|
||||
@@ -1308,7 +1210,7 @@ to retrieve the default arguments:</para>
|
||||
</programlisting>
|
||||
<para>
|
||||
Because of this, when wrapping C++ code, we had to resort to manual
|
||||
wrapping as outlined in the <ulink url="functions.html#overloading">previous section</ulink>, or
|
||||
wrapping as outlined in the <link linkend="python.overloading">previous section</link>, or
|
||||
writing thin wrappers:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -1401,7 +1303,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
See the <ulink url="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec">overloads reference</ulink>
|
||||
See the <ulink url="../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec">overloads reference</ulink>
|
||||
for details.</para>
|
||||
<anchor id="default_arguments.init_and_optional" /><bridgehead renderas="sect2">init and optional</bridgehead><para>
|
||||
A similar facility is provided for class constructors, again, with
|
||||
@@ -1479,12 +1381,12 @@ Notice though that we have a situation now where we have a minimum of zero
|
||||
It is important to emphasize however that <emphasis role="bold">the overloaded functions must
|
||||
have a common sequence of initial arguments</emphasis>. Otherwise, our scheme above
|
||||
will not work. If this is not the case, we have to wrap our functions
|
||||
<ulink url="functions.html#overloading">manually</ulink>.</para>
|
||||
<link linkend="python.overloading">manually</link>.</para>
|
||||
<para>
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> and
|
||||
its sister, <literal>BOOST_PYTHON_FUNCTION_OVERLOADS</literal>. Following up on our example
|
||||
presented in the section <ulink url="functions.html#overloading">on overloading</ulink>, since the
|
||||
presented in the section <link linkend="python.overloading">on overloading</link>, since the
|
||||
first 4 overload functins have a common sequence of initial arguments, we
|
||||
can use <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> to automatically wrap the
|
||||
first three of the <literal>def</literal>s and manually wrap just the last. Here's
|
||||
@@ -1525,7 +1427,7 @@ bidirectional mapping between C++ and Python while maintaining the Python
|
||||
feel. Boost.Python C++ <literal>object</literal>s are as close as possible to Python. This
|
||||
should minimize the learning curve significantly.</para>
|
||||
<para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/python.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/python.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
|
||||
<section id="python.basic_interface">
|
||||
<title>Basic Interface</title>
|
||||
@@ -1645,7 +1547,7 @@ member functions.</para>
|
||||
Demonstrates that you can write the C++ equivalent of <literal>"format" % x,y,z</literal>
|
||||
in Python, which is useful since there's no easy way to do that in std C++.</para>
|
||||
<para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/alert.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Beware</emphasis> the common pitfall of forgetting that the constructors
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Beware</emphasis> the common pitfall of forgetting that the constructors
|
||||
of most of Python's mutable types make copies, just as in Python.</para>
|
||||
<para>
|
||||
Python:</para>
|
||||
@@ -1721,7 +1623,7 @@ if</phrase><phrase role="special"> (</phrase><phrase role="identifier">x</phrase
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/tip.png"></imagedata></imageobject></inlinemediaobject> The astute reader might have noticed that the <literal>extract<T></literal>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/tip.png"></imagedata></imageobject></inlinemediaobject> The astute reader might have noticed that the <literal>extract<T></literal>
|
||||
facility in fact solves the mutable copying problem:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -1765,12 +1667,12 @@ associated with the C++ type passed as its first parameter.</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">what is a scope?</emphasis><para/>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">what is a scope?</emphasis><para/>
|
||||
<para/>
|
||||
The scope is a class that has an
|
||||
associated global Python object which controls the Python namespace in
|
||||
which new extension classes and wrapped functions will be defined as
|
||||
attributes. Details can be found <ulink url="../../../../v2/scope.html">here</ulink>.</entry>
|
||||
attributes. Details can be found <ulink url="../../../v2/scope.html">here</ulink>.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1814,7 +1716,7 @@ when embedding. Therefore you'll need to use the
|
||||
<ulink url="http://www.python.org/doc/current/api/api.html">Python/C API</ulink> to fill in
|
||||
the gaps. However, Boost.Python already makes embedding a lot easier and,
|
||||
in a future version, it may become unnecessary to touch the Python/C API at
|
||||
all. So stay tuned... <inlinemediaobject><imageobject><imagedata fileref="../images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
all. So stay tuned... <inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
<anchor id="embedding.building_embedded_programs" /><bridgehead renderas="sect2">Building embedded programs</bridgehead><para>
|
||||
To be able to use embedding in your programs, they have to be linked to
|
||||
both Boost.Python's and Python's static link library.</para>
|
||||
@@ -1823,8 +1725,8 @@ Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's <literal>/libs/python/build/bin-stage</literal> subdirectory. On Windows, the
|
||||
variants are called <literal>boost_python.lib</literal> (for release builds) and
|
||||
<literal>boost_python_debug.lib</literal> (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See <ulink url="../../../../building.html
|
||||
Building">and Testing</ulink> on how to do this.</para>
|
||||
you probably haven't built Boost.Python yet. See
|
||||
<ulink url="../../../building.html">Building and Testing</ulink> on how to do this.</para>
|
||||
<para>
|
||||
Python's static link library can be found in the <literal>/libs</literal> subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
@@ -1880,8 +1782,8 @@ There is a difference however. While the reference-counting is fully
|
||||
automatic in Python, the Python/C API requires you to do it
|
||||
<ulink url="http://www.python.org/doc/current/api/refcounts.html">by hand</ulink>. This is
|
||||
messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the <ulink url="../../v2/handle.html">handle</ulink> and
|
||||
<ulink url="../../../../v2/object.html">object</ulink> class templates to automate the process.</para>
|
||||
Fortunately Boost.Python provides the <ulink url="../../../v2/handle.html">handle</ulink> and
|
||||
<ulink url="../../../v2/object.html">object</ulink> class templates to automate the process.</para>
|
||||
<anchor id="using_the_interpreter.reference_counting_handles_and_objects" /><bridgehead renderas="sect2">Reference-counting handles and objects</bridgehead><para>
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
<literal>PyObject*</literal>: as a <emphasis>borrowed reference</emphasis> or as a <emphasis>new reference</emphasis>. Which of
|
||||
@@ -1891,7 +1793,7 @@ be 'handled' by Boost.Python.</para>
|
||||
<para>
|
||||
For a function returning a <emphasis>borrowed reference</emphasis> we'll have to tell the
|
||||
<literal>handle</literal> that the <literal>PyObject*</literal> is borrowed with the aptly named
|
||||
<ulink url="../../../../v2/handle.html#borrowed-spec">borrowed</ulink> function. Two functions
|
||||
<ulink url="../../../v2/handle.html#borrowed-spec">borrowed</ulink> function. Two functions
|
||||
returning borrowed references are <ulink url="http://www.python.org/doc/current/api/importing.html#l2h-125">PyImport_AddModule</ulink> and <ulink url="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594">PyModule_GetDict</ulink>.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
@@ -1915,7 +1817,7 @@ discuss in the next section.</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Handle is a class <emphasis>template</emphasis>, so why haven't we been using any template parameters?</emphasis><para/>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Handle is a class <emphasis>template</emphasis>, so why haven't we been using any template parameters?</emphasis><para/>
|
||||
|
||||
<para/>
|
||||
|
||||
@@ -1993,7 +1895,7 @@ the object's <literal>ptr</literal> member function to retrieve the <literal>PyO
|
||||
This should create a file called 'hello.txt' in the current directory
|
||||
containing a phrase that is well-known in programming circles.</para>
|
||||
<para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that we wrap the return value of <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> in a
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that we wrap the return value of <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> in a
|
||||
(nameless) <literal>handle</literal> even though we are not interested in it. If we didn't
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap <literal>PyObject*</literal>s in <literal>handle</literal>s.</para>
|
||||
@@ -2042,15 +1944,15 @@ int</phrase><phrase role="identifier"> five_squared</phrase><phrase role="specia
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that <literal>object</literal>'s member function to return the wrapped
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that <literal>object</literal>'s member function to return the wrapped
|
||||
<literal>PyObject*</literal> is called <literal>ptr</literal> instead of <literal>get</literal>. This makes sense if you
|
||||
take into account the different functions that <literal>object</literal> and <literal>handle</literal>
|
||||
perform.</para>
|
||||
<anchor id="using_the_interpreter.exception_handling" /><bridgehead renderas="sect2">Exception handling</bridgehead><para>
|
||||
If an exception occurs in the execution of some Python code, the <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink>
|
||||
function returns a null pointer. Constructing a <literal>handle</literal> out of this null
|
||||
pointer throws <ulink url="../../../../v2/errors.html#error_already_set-spec">error_already_set</ulink>,
|
||||
so basically, the Python exception is automatically translated into a
|
||||
If an exception occurs in the execution of some Python code, the <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink>
|
||||
function returns a null pointer. Constructing a <literal>handle</literal> out of this null
|
||||
pointer throws <ulink url="../../../v2/errors.html#error_already_set-spec">error_already_set</ulink>,
|
||||
so basically, the Python exception is automatically translated into a
|
||||
C++ exception when using <literal>handle</literal>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -2073,14 +1975,14 @@ catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_a
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
The <literal>error_already_set</literal> exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
<ulink url="http://www.python.org/doc/api/exceptionHandling.html">exception handling functions</ulink>
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
<ulink url="http://www.python.org/doc/api/exceptionHandling.html#l2h-70">PyErr_Print()</ulink> to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the <ulink url="http://www.python.org/doc/api/standardExceptions.html">
|
||||
standard exceptions</ulink>:</para>
|
||||
The <literal>error_already_set</literal> exception class doesn't carry any information in itself.
|
||||
To find out more about the Python exception that occurred, you need to use the
|
||||
<ulink url="http://www.python.org/doc/api/exceptionHandling.html">exception handling functions</ulink>
|
||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
||||
<ulink url="http://www.python.org/doc/api/exceptionHandling.html#l2h-70">PyErr_Print()</ulink> to
|
||||
print the exception's traceback to the console, or comparing the type of the
|
||||
exception with those of the <ulink url="http://www.python.org/doc/api/standardExceptions.html
|
||||
standard">exceptions</ulink>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
<phrase role="keyword">catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_already_set</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||
@@ -2098,11 +2000,11 @@ standard exceptions</ulink>:</para>
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
(To retrieve even more information from the exception you can use some of the other
|
||||
exception handling functions listed <ulink url="http://www.python.org/doc/api/exceptionHandling.html">here</ulink>.)</para>
|
||||
<para>
|
||||
If you'd rather not have <literal>handle</literal> throw a C++ exception when it is constructed, you
|
||||
can use the <ulink url="../../v2/handle.html#allow_null-spec">allow_null</ulink> function in the same
|
||||
If you'd rather not have <literal>handle</literal> throw a C++ exception when it is constructed, you
|
||||
can use the <ulink url="../../../v2/handle.html#allow_null-spec">allow_null</ulink> function in the same
|
||||
way you'd use borrowed:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -2325,7 +2227,7 @@ Compiling these files will generate the following Python extensions:
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> The extension <literal>.pyd</literal> is used for python extension modules, which
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> The extension <literal>.pyd</literal> is used for python extension modules, which
|
||||
are just shared libraries. Using the default for your system, like <literal>.so</literal> for
|
||||
Unix and <literal>.dll</literal> for Windows, works just as well.</entry>
|
||||
</row>
|
||||
@@ -2345,7 +2247,7 @@ actually a Python package. It can be a empty file, but can also perform some
|
||||
magic, that will be shown later.</para>
|
||||
<para>
|
||||
Now our package is ready. All the user has to do is put <literal>sounds</literal> into his
|
||||
<ulink url="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000">PYTHONPATH</ulink>
|
||||
<ulink url="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000">PYTHONPATH</ulink>
|
||||
and fire up the interpreter:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -2477,7 +2379,7 @@ A</phrase><phrase role="identifier"> C</phrase><phrase role="identifier"> instan
|
||||
</literal>
|
||||
</programlisting>
|
||||
<para>
|
||||
Yes, Python rox. <inlinemediaobject><imageobject><imagedata fileref="../images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
Yes, Python rox. <inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
|
||||
<para>
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class <literal>point</literal> in C++:</para>
|
||||
@@ -2493,7 +2395,7 @@ BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="ident
|
||||
</programlisting>
|
||||
<para>
|
||||
If we are using the technique from the previous session,
|
||||
<ulink url="techniques.html#creating_packages">Creating Packages</ulink>, we can code directly
|
||||
<link linkend="python.creating_packages">Creating Packages</link>, we can code directly
|
||||
into <literal>geom/<emphasis role="underline">_init</emphasis>_.py</literal>:</para>
|
||||
<programlisting>
|
||||
<literal>
|
||||
@@ -2643,7 +2545,7 @@ the compilation of a single cpp, instead of the entire wrapper code.</para>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> If you're exporting your classes with <ulink url="../../../../../pyste/index.html">Pyste</ulink>,
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> If you're exporting your classes with <ulink url="../../../../pyste/index.html">Pyste</ulink>,
|
||||
take a look at the <literal>--multiple</literal> option, that generates the wrappers in
|
||||
various files as demonstrated here.</entry>
|
||||
</row>
|
||||
@@ -2656,9 +2558,9 @@ various files as demonstrated here.</entry>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<inlinemediaobject><imageobject><imagedata fileref="../images/note.png"></imagedata></imageobject></inlinemediaobject> This method is useful too if you are getting the error message
|
||||
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> This method is useful too if you are getting the error message
|
||||
<emphasis>"fatal error C1204:Compiler limit:internal structure overflow"</emphasis> when compiling
|
||||
a large source file, as explained in the <ulink url="../../../../v2/faq.html#c1204">FAQ</ulink>.</entry>
|
||||
a large source file, as explained in the <ulink url="../../../v2/faq.html#c1204">FAQ</ulink>.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
||||
@@ -158,6 +158,6 @@ documentation).
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
||||
|
||||
<td>An MPL unary <a href=
|
||||
"../../../mpl/doc/paper/html/usage.html#metafunctions.classes">Metafunction
|
||||
"../../../mpl/doc/refmanual/metafunction-class.html">Metafunction
|
||||
Class</a> used produce the "preliminary" result object.</td>
|
||||
</tr>
|
||||
|
||||
@@ -141,8 +141,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this software is
|
||||
granted provided this copyright notice appears in all copies. This
|
||||
|
||||
@@ -61,7 +61,7 @@ type <code>T</code>. In addition, all pointers are Dereferenceable.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002-2003. </i>
|
||||
|
||||
<p>Permission to copy, use, modify, sell
|
||||
and distribute this software is granted provided this copyright notice appears
|
||||
|
||||
@@ -83,7 +83,7 @@ are layout-compatible with PyObject.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
<p>Permission to copy, use, modify, sell
|
||||
and distribute this software is granted provided this copyright notice appears
|
||||
|
||||
@@ -61,7 +61,7 @@ type.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
<p>Permission to copy, use, modify, sell
|
||||
and distribute this software is granted provided this copyright notice appears
|
||||
|
||||
@@ -221,6 +221,6 @@ you'll just have to wait till next month (hopefully the beginning).
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -229,6 +229,6 @@ worth doing anything about it.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -303,6 +303,6 @@ to these issues will probably have to be formalized before long.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -144,13 +144,7 @@ instances of the associated Python type will be considered a match.
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this software is
|
||||
granted provided this copyright notice appears in all copies. This
|
||||
software is provided "as is" without express or implied warranty, and
|
||||
with no claim as to its suitability for any purpose.</p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ C++ function return type.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
<p>Permission to copy, use, modify, sell
|
||||
and distribute this software is granted provided this copyright notice appears
|
||||
|
||||
@@ -126,8 +126,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -190,8 +190,7 @@ BOOST_PYTHON_MODULE(xxx)
|
||||
<p>Revised 01 August, 2003</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
||||
Rights Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -77,6 +77,6 @@ double apply2(PyObject* func, double x, double y)
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -152,8 +152,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -245,8 +245,7 @@ void apply(PyObject* callable, X& x)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -730,7 +730,7 @@ class_& enable_pickling();
|
||||
<h3><a name="bases-spec"></a>Class template
|
||||
<code>bases<T1, T2,</code>...<code>TN></code></h3>
|
||||
|
||||
<p>An <a href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a>
|
||||
<p>An <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a>
|
||||
which can be used in <code>class_<</code>...<code>></code>
|
||||
instantiations indicate a list of base classes.</p>
|
||||
|
||||
@@ -794,8 +794,7 @@ class_<Derived, bases<Base> >("Derived");
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -146,8 +146,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE_INIT(data_members_example)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -182,8 +182,7 @@ BOOST_PYTHON_MODULE(def_test)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -132,4 +132,4 @@ BOOST_PYTHON_MODULE(my_ext)
|
||||
</p>
|
||||
|
||||
|
||||
<p><i>© Copyright Joel de Guzman 2003. All Rights Reserved.</i>
|
||||
<p><i>© Copyright Joel de Guzman 2003. </i>
|
||||
@@ -166,5 +166,5 @@ struct return_value_policy : Base
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -93,8 +93,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -143,8 +143,7 @@ dict swap_object_dict(object target, dict d)
|
||||
<p>Revised 30 September, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -225,8 +225,7 @@ TypeError: bad argument type for built-in operation
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ void handle_exception() throw();
|
||||
<dl class="handle_exception-semantics">
|
||||
<dt><b>Requires:</b> The first form requires that the expression
|
||||
<code><a href=
|
||||
"../../../function/doc/reference.html#functionN">function0</a><void>(f)</code>
|
||||
"../../../../doc/html/functionN.html">function0</a><void>(f)</code>
|
||||
is valid. The second form requires that a C++ exception is currently
|
||||
being handled (see section 15.1 in the C++ standard).</dt>
|
||||
|
||||
@@ -280,8 +280,7 @@ same_name2(PyObject* args, PyObject* keywords)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -141,8 +141,7 @@ BOOST_PYTHON_MODULE(exception_translator_ext)
|
||||
<p>Revised 03 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -223,8 +223,7 @@ BOOST_PYTHON_MODULE(extract_ext)
|
||||
<p>Revised 15 November, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -649,14 +649,14 @@ void b_insert(B& b, std::auto_ptr<A> a)
|
||||
<h2><a name="slow_compilation">Compilation takes too much time and eats too
|
||||
much memory! What can I do to make it faster?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/reducing_compiling_time.html"
|
||||
Please refer to the <a href="../tutorial/doc/html/python/techniques.html#python.reducing_compiling_time"
|
||||
>Reducing Compiling Time</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/creating_packages.html"
|
||||
Please refer to the <a href="../tutorial/doc/html/python/techniques.html#python.creating_packages"
|
||||
>Creating Packages</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
@@ -878,7 +878,6 @@ BOOST_PYTHON_MODULE(custom_string)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
||||
Rights Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -362,5 +362,5 @@
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.
|
||||
2002.
|
||||
|
||||
|
||||
@@ -161,5 +161,5 @@ std::size_t length_if_string(PyObject* p)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -326,8 +326,8 @@ null_ok<T>* allow_null(T* p)
|
||||
</p>
|
||||
|
||||
<p class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||
.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace boost { namespace python
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
<p>A "<a href="../../../mpl/doc/paper/html/usage.html#metafunctions">
|
||||
<p>A "<a href="../../../mpl/doc/refmanual/metafunction.html">
|
||||
metafunction</a>" that is inspected by Boost.Python to determine how
|
||||
wrapped classes can be constructed.</p>
|
||||
|
||||
@@ -215,8 +215,8 @@ BOOST_PYTHON_MODULE(back_references)
|
||||
</p>
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||
.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -284,5 +284,5 @@ namespace boost
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -154,8 +154,7 @@ BOOST_PYTHON_MODULE(implicit_ext)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
||||
<i>unspecified</i><code>></code></h3>
|
||||
|
||||
<p>A <a href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a> which
|
||||
<p>A <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> which
|
||||
can be used to specify a family of one or more <code>__init__</code>
|
||||
functions. Only the last <code>T</code><i><small>i</small></i> supplied
|
||||
may be an instantiation of <a href=
|
||||
@@ -195,7 +195,7 @@ template <class Policies>
|
||||
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
||||
<i>unspecified</i><code>></code></h3>
|
||||
|
||||
<p>A <a href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a> which
|
||||
<p>A <a href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> which
|
||||
can be used to specify the optional arguments to an <code>__init__</code>
|
||||
function.</p>
|
||||
|
||||
@@ -242,8 +242,7 @@ class_<X>("X", "This is X's docstring.",
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/instance_holder.hpp></title>
|
||||
</head>
|
||||
|
||||
<style type="text/css">
|
||||
p.c4 {font-style: italic}
|
||||
span.c3 {color: #ff0000}
|
||||
@@ -13,6 +18,7 @@
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
||||
summary="header">
|
||||
<tr>
|
||||
@@ -204,6 +210,7 @@ struct pointer_holder : instance_holder
|
||||
|
||||
|
||||
<p class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
||||
Rights Reserved.
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -380,7 +380,8 @@ BOOST_PYTHON_MODULE(demo)
|
||||
<dt><code><a href=
|
||||
"../../test/iterator.py">libs/python/test/input_iterator.py</a></code></dt>
|
||||
|
||||
<dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
@@ -388,10 +389,7 @@ BOOST_PYTHON_MODULE(demo)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
||||
Rights Reserved.</i></p>
|
||||
</dd>
|
||||
</dl>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -133,8 +133,7 @@ long zeroes(list l)
|
||||
<p>Revised 1 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -110,8 +110,7 @@ python::long_ fact(long n)
|
||||
<p>Revised 1 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -292,8 +292,7 @@ BOOST_PYTHON_MODULE(noddy_cache)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ template <class F, class Policies, class Keywords, class Signature>
|
||||
arguments of the resulting function.
|
||||
<li>If <code>Signature</code>
|
||||
is supplied, it should be an instance of an <a
|
||||
href="../../../mpl/doc/ref/Sequence.html">MPL front-extensible
|
||||
href="../../../mpl/doc/refmanual/front-extensible-sequence.html">MPL front-extensible
|
||||
sequence</a> representing the function's return type followed by
|
||||
its argument types. Pass a <code>Signature</code> when wrapping
|
||||
function object types whose signatures can't be deduced, or when
|
||||
@@ -135,7 +135,7 @@ template <class ArgList, class Generator, class Policies>
|
||||
<dt><b>Requires:</b> <code>T</code> is a class type.
|
||||
<code>Policies</code> is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>. <code>ArgList</code> is an <a
|
||||
href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a> of C++ argument
|
||||
href="../../../mpl/doc/refmanual/forward-sequence.html">MPL sequence</a> of C++ argument
|
||||
types (<i>A1, A2,... AN</i>) such that if
|
||||
<code>a1, a2</code>... <code>aN</code> are objects of type
|
||||
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
||||
@@ -201,8 +201,7 @@ BOOST_PYTHON_MODULE(make_function_test)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -136,8 +136,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -104,5 +104,5 @@ RuntimeError: Unidentifiable C++ Exception
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -261,8 +261,7 @@ void set_first_element(numeric::array& y, double value)
|
||||
<p>Revised 03 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -927,8 +927,7 @@ object sum_items(object seq)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -900,8 +900,7 @@ BOOST_PYTHON_MODULE(demo)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ struct X
|
||||
Y inner;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 1, 3)
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(f_member_overloads, f, 1, 3)
|
||||
|
||||
BOOST_PYTHON_MODULE(args_ext)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ BOOST_PYTHON_MODULE(args_ext)
|
||||
|
||||
class_<X>("X", "This is X's docstring")
|
||||
.def("f1", &X::f,
|
||||
X_f_overloads(
|
||||
f_member_overloads(
|
||||
args("x", "y", "z"), "f's docstring"
|
||||
)[return_internal_reference<>()]
|
||||
)
|
||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE(args_ext)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -43,6 +43,6 @@
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -315,7 +315,7 @@ class we make all instances pickleable:
|
||||
</pre>
|
||||
|
||||
See also the
|
||||
<a href="../tutorial/doc/extending_wrapped_objects_in_python.html"
|
||||
<a href="../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python"
|
||||
>tutorial section</a> on injecting additional methods from Python.
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -133,8 +133,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -112,5 +112,5 @@ BOOST_PYTHON_MODULE(pointee_demo)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -39,6 +39,6 @@ design decisions and links to relevant discussions.
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -259,5 +259,5 @@ void pass_as_arg(expensive_to_copy* x, PyObject* f)
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -101,8 +101,7 @@
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -109,8 +109,7 @@ Python:
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
p.c3 {font-style: italic}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -96,158 +96,217 @@
|
||||
|
||||
<h2><a name="high_level">High Level Components</a></h2>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
|
||||
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
||||
<dt><a href=
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a></dt>
|
||||
<dt><a href=
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"module.html#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="wrapper.html">wrapper.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="wrapper.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="wrapper.html#override-spec">override</a></dt>
|
||||
|
||||
<dt><a href="wrapper.html#wrapper-spec">wrapper</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="object_wrappers">Object Wrappers</a></h2>
|
||||
|
||||
@@ -357,6 +416,7 @@
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="slice.html">slice.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
@@ -978,22 +1038,24 @@
|
||||
|
||||
<h2><a name="topics">Topics</a></h2>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt><a href="callbacks.html">Calling Python Functions and Methods</a></dt>
|
||||
<dt><a href="pickle.html">Pickle Support</a><br>
|
||||
<a href="indexing.html">Indexing Support</a></dt>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><a href="callbacks.html">Calling Python Functions and
|
||||
Methods</a></dt>
|
||||
|
||||
<dt><a href="pickle.html">Pickle Support</a><br>
|
||||
<a href="indexing.html">Indexing Support</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
19 July, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
31 October, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||
.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -171,8 +171,7 @@ BOOST_PYTHON_MODULE(singleton)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ TypeError: No to_python (by-value) converter found for C++ type: class boost::sh
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
2002. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ BOOST_PYTHON_MODULE(return_self_ext)
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> and Nikolay
|
||||
Mladenov 2003. All Rights Reserved.</i></p>
|
||||
Mladenov 2003. </i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE(internal_refs)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -158,8 +158,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -163,8 +163,7 @@ BOOST_PYTHON_MODULE(nested)
|
||||
<p>Revised 09 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -228,8 +228,7 @@ str remove_angle_brackets(str x)
|
||||
<p>Revised 3 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -197,8 +197,7 @@ BOOST_PYTHON_MODULE(to_python_converter)
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -190,5 +190,5 @@ struct reference_existing_object
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -97,5 +97,5 @@ PyObject* operator()(argument_type x) const;
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
|
||||
|
||||
@@ -130,8 +130,7 @@ tuple head_and_tail(object sequence)
|
||||
<p>Revised 03 October, 2002</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/type_id.hpp></title>
|
||||
<style type="text/css">
|
||||
|
||||
<style type="text/css">
|
||||
p.c4 {font-style: italic}
|
||||
span.c3 {color: #ff0000}
|
||||
h2.c2 {text-align: center}
|
||||
@@ -31,39 +32,41 @@
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a>
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a>
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#type_info-spec">Class
|
||||
<code>type_info</code></a>
|
||||
<dt><a href="#type_info-spec">Class <code>type_info</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#type_info-spec-synopsis">Class
|
||||
<code>type_info</code> synopsis</a>
|
||||
<code>type_info</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#type_infospec-ctors">Class
|
||||
<code>type_info</code> constructor</a>
|
||||
<dt><a href="#type_infospec-ctors">Class <code>type_info</code>
|
||||
constructor</a></dt>
|
||||
|
||||
<dt><a href="#type_infospec-comparisons">Class
|
||||
<code>type_info</code> comparison functions</a>
|
||||
<code>type_info</code> comparison functions</a></dt>
|
||||
|
||||
<dt><a href="#type_infospec-observers">Class
|
||||
<code>type_info</code> observer functions</a>
|
||||
<code>type_info</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#functions">Functions</a>
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#type_id-spec">type_id</a>
|
||||
<dt><a href="#type_id-spec">type_id</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a>
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
@@ -71,9 +74,9 @@
|
||||
|
||||
<p><code><boost/python/type_id.hpp></code> provides types and
|
||||
functions for runtime type identification like those of of
|
||||
<code><typeinfo></code>. It exists mostly to work around
|
||||
certain compiler bugs and platform-dependent interactions with
|
||||
shared libraries.
|
||||
<code><typeinfo></code>. It exists mostly to work around certain
|
||||
compiler bugs and platform-dependent interactions with shared
|
||||
libraries.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
@@ -81,19 +84,17 @@
|
||||
|
||||
<p><code>type_info</code> instances identify a type. As
|
||||
<code>std::type_info</code> is specified to (but unlike its
|
||||
implementation in some compilers),
|
||||
<code>boost::python::type_info</code> never represents top-level
|
||||
references or cv-qualification (see section 5.2.8 in the C++
|
||||
standard). Unlike <code>std::type_info</code>,
|
||||
implementation in some compilers), <code>boost::python::type_info</code>
|
||||
never represents top-level references or cv-qualification (see section
|
||||
5.2.8 in the C++ standard). Unlike <code>std::type_info</code>,
|
||||
<code>boost::python::type_info</code> instances are copyable, and
|
||||
comparisons always work reliably across shared library boundaries.
|
||||
comparisons always work reliably across shared library boundaries.</p>
|
||||
|
||||
<h4><a name="type_info-spec-synopsis"></a>Class type_info
|
||||
synopsis</h4>
|
||||
<h4><a name="type_info-spec-synopsis"></a>Class type_info synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class type_info : <a href=
|
||||
class type_info : <a href=
|
||||
"../../../utility/operators.htm#totally_ordered1">totally_ordered</a><type_info>
|
||||
{
|
||||
public:
|
||||
@@ -117,41 +118,41 @@ type_info(std::type_info const& = typeid(void));
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> constructs a <code>type_info</code> object
|
||||
which identifies the same type as its argument.
|
||||
<dt><b>Effects:</b> constructs a <code>type_info</code> object which
|
||||
identifies the same type as its argument.</dt>
|
||||
|
||||
<dt><b>Rationale:</b> Since it is occasionally neccessary to make
|
||||
an array of <code>type_info</code> objects a benign default
|
||||
argument is supplied. <span class="c3"><b>Note:</b></span> this
|
||||
constructor does <i>not</i> correct for non-conformance of
|
||||
compiler <code>typeid()</code> implementations. See <code><a
|
||||
href="#type_id-spec">type_id</a></code>, below.
|
||||
<dt><b>Rationale:</b> Since it is occasionally neccessary to make an
|
||||
array of <code>type_info</code> objects a benign default argument is
|
||||
supplied. <span class="c3"><b>Note:</b></span> this constructor does
|
||||
<i>not</i> correct for non-conformance of compiler
|
||||
<code>typeid()</code> implementations. See <code><a href=
|
||||
"#type_id-spec">type_id</a></code>, below.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="type_infospec-comparisons">Class
|
||||
<code>type_info</code> comparisons</a></h4>
|
||||
<h4><a name="type_infospec-comparisons">Class <code>type_info</code>
|
||||
comparisons</a></h4>
|
||||
<pre>
|
||||
bool operator<(type_info const& rhs) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> yields a total order over
|
||||
<code>type_info</code> objects.
|
||||
<dt><b>Effects:</b> yields a total order over <code>type_info</code>
|
||||
objects.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
bool operator==(type_info const& rhs) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>true</code> iff the two values describe
|
||||
the same type.
|
||||
<dt><b>Returns:</b> <code>true</code> iff the two values describe the
|
||||
same type.</dt>
|
||||
</dl>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Note:</b> The use of <code><a href=
|
||||
<dt><b>Note:</b> The use of <code><a href=
|
||||
"../../../utility/operators.htm#totally_ordered1">totally_ordered</a><type_info></code>
|
||||
as a private base class supplies operators <code><=</code>,
|
||||
<code>>=</code>, <code>></code>, and <code>!=</code>
|
||||
<code>>=</code>, <code>></code>, and <code>!=</code></dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="type_infospec-observers">Class <code>type_info</code>
|
||||
@@ -161,8 +162,8 @@ char const* name() const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> The result of calling <code>name()</code> on
|
||||
the argument used to construct the object.
|
||||
<dt><b>Returns:</b> The result of calling <code>name()</code> on the
|
||||
argument used to construct the object.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
@@ -171,25 +172,25 @@ std::ostream& operator<<(std::ostream&s, type_info const&x);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Writes a description of the type described by
|
||||
to <code>x</code> into <code>s</code>.
|
||||
<dt><b>Effects:</b> Writes a description of the type described by to
|
||||
<code>x</code> into <code>s</code>.</dt>
|
||||
|
||||
<dt><b>Rationale:</b> Not every C++ implementation provides a
|
||||
truly human-readable <code>type_info::name()</code> string, but
|
||||
for some we may be able to decode the string and produce a
|
||||
reasonable representation.
|
||||
<dt><b>Rationale:</b> Not every C++ implementation provides a truly
|
||||
human-readable <code>type_info::name()</code> string, but for some we
|
||||
may be able to decode the string and produce a reasonable
|
||||
representation.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="type_id-spec">template <class T> type_info type_id</a>()
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Returns:</b> <code>type_info(typeid(T))</code>
|
||||
<dt><b>Returns:</b> <code>type_info(typeid(T))</code></dt>
|
||||
|
||||
<dt><b>Note:</b> On some non-conforming C++ implementations, the
|
||||
code is not actually as simple as described above; the semantics
|
||||
are adjusted to work <i>as-if</i> the C++ implementation were
|
||||
conforming.
|
||||
<dt><b>Note:</b> On some non-conforming C++ implementations, the code
|
||||
is not actually as simple as described above; the semantics are
|
||||
adjusted to work <i>as-if</i> the C++ implementation were
|
||||
conforming.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
@@ -209,11 +210,13 @@ bool is_int(T x)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</p>
|
||||
|
||||
<p class="c4">© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
||||
Rights Reserved.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ struct return_internal_reference
|
||||
</p>
|
||||
<p>
|
||||
<i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002. </i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
236
doc/v2/wrapper.html
Executable file
236
doc/v2/wrapper.html
Executable file
@@ -0,0 +1,236 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <wrapper.hpp></title>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header <wrapper.hpp></h2>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#override-spec">Class template
|
||||
<code>override</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#override-spec-synopsis">Class
|
||||
<code>override</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#override-spec-observers">Class
|
||||
<code>override</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#wrapper-spec">Class template
|
||||
<code>wrapper</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#wrapper-spec-synopsis">Class <code>wrapper</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#wrapper-spec-observers">Class
|
||||
<code>wrapper</code> observer functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>To wrap a class <code>T</code> 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.</p>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="override-spec"></a>Class <code>override</code></h3>
|
||||
|
||||
<p>Encapsulates a Python override of a C++ virtual function. An
|
||||
<code>override</code> object either holds a callable Python object or
|
||||
<code>None</code>.</p>
|
||||
|
||||
<h4><a name="override-spec-synopsis"></a>Class <code>override</code>
|
||||
synopsis</h4>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class override : object
|
||||
{
|
||||
public:
|
||||
<i>unspecified</i> operator() const;
|
||||
template <class A0>
|
||||
<i>unspecified</i> operator(A0) const;
|
||||
template <class A0, class A1>
|
||||
<i>unspecified</i> operator(A0, A1) const;
|
||||
...
|
||||
template <class A0, class A1, ...class A<i>n</i>>
|
||||
<i>unspecified</i> operator(A0, A1, ...A<i>n</i>) const;
|
||||
};
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h4><a name="override-spec-observers"></a>Class <code>override</code>
|
||||
observer functions</h4>
|
||||
<pre>
|
||||
<i>unspecified</i> operator() const;
|
||||
template <class A0>
|
||||
<i>unspecified</i> operator(A0) const;
|
||||
template <class A0, class A1>
|
||||
<i>unspecified</i> operator(A0, A1) const;
|
||||
...
|
||||
template <class A0, class A1, ...class A<i>n</i>>
|
||||
<i>unspecified</i> operator(A0, A1, ...A<i>n</i>) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> If <code>*this</code> holds a callable Python
|
||||
object, it is invoked with the specified arguments in the manner
|
||||
specified <a href="callbacks.html">here</a>. Otherwise, throws <code><a
|
||||
href="errors.html#error_already_set-spec">error_already_set</a></code>
|
||||
.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An object of unspecified type that holds the Python
|
||||
result of the invocation and, when converted to a C++ type
|
||||
<code>R</code>, attempts to convert that result object to
|
||||
<code>R</code>. If that conversion fails, throws <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code>
|
||||
.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="wrapper-spec"></a>Class template <code>wrapper</code></h3>
|
||||
|
||||
<p>Deriving your wrapper class from both ``T`` <i>and</i>
|
||||
``wrapper<T> makes writing that derived class easier.</p>
|
||||
|
||||
<h4><a name="wrapper-spec-synopsis"></a>Class template
|
||||
<code>wrapper</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class wrapper
|
||||
{
|
||||
protected:
|
||||
override get_override(char const* name) const;
|
||||
};
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h4><a name="wrapper-spec-observers"></a>Class <code>wrapper</code>
|
||||
observer functions</h4>
|
||||
<pre>
|
||||
override get_override(char const* name) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>name</code> is a <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> If <code>*this</code> is the C++ base class
|
||||
subobject of a Python derived class instance that overrides the named
|
||||
function, returns an <code>override</code> object that delegates to the
|
||||
Python override. Otherwise, returns an <code>override</code> object
|
||||
that holds <code>None</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
<pre>
|
||||
#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()
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
|
||||
return call<char const*>(this->get_override("f").ptr());
|
||||
#else
|
||||
return this->get_override("f")();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// 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"))
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
|
||||
return call<char const*>(f.ptr());
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
|
||||
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)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
31 October, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2004</i>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright Joel de Guzman 2002-2004. 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)
|
||||
// Hello World Example from the tutorial
|
||||
// [Joel de Guzman 10/9/2002]
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ GCCXML</a> to
|
||||
parse all the headers and extract the necessary information to automatically
|
||||
generate C++ code.</p>
|
||||
<a name="example"></a><h2>Example</h2><p>
|
||||
Let's borrow the class <tt>World</tt> from the <a href="../../doc/tutorial/doc/exposing_classes.html">
|
||||
Let's borrow the class <tt>World</tt> from the <a href="../../doc/tutorial/doc/html/python/exposing.html">
|
||||
tutorial</a>: </p>
|
||||
<code><pre>
|
||||
<span class=keyword>struct </span><span class=identifier>World
|
||||
|
||||
@@ -29,7 +29,7 @@ Even thought Pyste can identify various elements in the C++ code, like virtual
|
||||
member functions, attributes, and so on, one thing that it can't do is to
|
||||
guess the semantics of functions that return pointers or references. In this
|
||||
case, the user must manually specify the policy. Policies are explained in the
|
||||
<a href="../../doc/tutorial/doc/call_policies.html">
|
||||
<a href="../../doc/tutorial/doc/html/python/functions.html#python.call_policies">
|
||||
tutorial</a>.</p>
|
||||
<p>
|
||||
The policies in Pyste are named exactly as in <a href="../../index.html">
|
||||
|
||||
@@ -116,7 +116,7 @@ So, the usage is simple enough:</p>
|
||||
<code><pre>>python pyste.py --module=mymodule file.pyste file2.pyste ...</pre></code><p>
|
||||
will generate a file <tt>mymodule.cpp</tt> in the same dir where the command was
|
||||
executed. Now you can compile the file using the same instructions of the
|
||||
<a href="../../doc/tutorial/doc/building_hello_world.html">
|
||||
<a href="../../doc/tutorial/doc/html/python/hello.html">
|
||||
tutorial</a>. </p>
|
||||
<a name="wait____how_do_i_set_those_i_and_d_flags_"></a><h2>Wait... how do I set those I and D flags?</h2><p>
|
||||
Don't worry: normally <a href="http://www.gccxml.org">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>Pyste Documentation</title>
|
||||
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
|
||||
<link rel="next" href="introduction.html">
|
||||
<link rel="next" href="doc/introduction.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user