mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 16:52:15 +00:00
Compare commits
24 Commits
develop
...
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 @@
|
|||||||
+++++++++++++++++++++++++++++++++++++++++++
|
This file has been moved to http://www.boost-consulting.com/writing/bpl.txt.
|
||||||
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
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,24 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt>8 Sept 2004</dt>
|
<dt>19 November 2004 - 1.32 release</dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<ul>
|
<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
|
Support for Python's Bool type, thanks to <a
|
||||||
mailto="dholth-at-fastmail.fm">Daniel Holth</a>.
|
mailto="dholth-at-fastmail.fm">Daniel Holth</a>.
|
||||||
</ul>
|
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt>11 Sept 2003</dt>
|
<dt>11 Sept 2003</dt>
|
||||||
@@ -189,12 +200,12 @@ BOOST_PYTHON_MODULE(test)
|
|||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -384,7 +384,7 @@
|
|||||||
15 July, 2003</p>
|
15 July, 2003</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<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>
|
</body>
|
||||||
</html>
|
</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 ;
|
import boostbook : boostbook ;
|
||||||
|
|
||||||
boostbook tutorial : tutorial.xml
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title>Chapter 1. python 1.0</title>
|
<title>Chapter 1. python 1.0</title>
|
||||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="index.html" title="Chapter 1. python 1.0">
|
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||||
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../boost.png"></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="../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="libraries.html">Libraries</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="../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
<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="chapter" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div>
|
||||||
<div>
|
|
||||||
<div><h2 class="title">
|
<div><h2 class="title">
|
||||||
<a name="python"></a>Chapter 1. python 1.0</h2></div>
|
<a name="python"></a>Chapter 1. python 1.0</h2></div>
|
||||||
<div><div class="author"><h3 class="author">
|
<div><div class="author"><h3 class="author">
|
||||||
@@ -30,17 +29,17 @@
|
|||||||
<span class="firstname">David</span> <span class="surname">Abrahams</span>
|
<span class="firstname">David</span> <span class="surname">Abrahams</span>
|
||||||
</h3></div></div>
|
</h3></div></div>
|
||||||
<div><p class="copyright">Copyright © 2002-2004 Joel de Guzman, David Abrahams</p></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.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
<a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
<a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||||
http://www.boost.org/LICENSE_1_0.txt
|
http://www.boost.org/LICENSE_1_0.txt
|
||||||
</a>)
|
</a>)
|
||||||
|
|
||||||
</p></div></div>
|
</p>
|
||||||
</div>
|
</div></div>
|
||||||
<div></div>
|
</div></div>
|
||||||
</div>
|
|
||||||
<div class="toc">
|
<div class="toc">
|
||||||
<p><b>Table of Contents</b></p>
|
<p><b>Table of Contents</b></p>
|
||||||
<dl>
|
<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.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.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.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.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>
|
<dt><span class="section"><a href="python/exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||||
</dl></dd>
|
</dl></dd>
|
||||||
@@ -84,11 +82,8 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.quickstart"></a>QuickStart</h2></div></div></div>
|
||||||
<a name="python.quickstart"></a>QuickStart</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
The Boost Python Library is a framework for interfacing Python and
|
The Boost Python Library is a framework for interfacing Python and
|
||||||
C++. It allows you to quickly and seamlessly expose C++ classes
|
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
|
wrapping code takes on the look of a kind of declarative interface
|
||||||
definition language (IDL).</p>
|
definition language (IDL).</p>
|
||||||
<a name="quickstart.hello_world"></a><h2>
|
<a name="quickstart.hello_world"></a><h2>
|
||||||
<a name="id344076"></a>Hello World</h2>
|
<a name="id376600"></a>Hello World</h2>
|
||||||
<p>
|
<p>
|
||||||
Following C/C++ tradition, let's start with the "hello, world". A C++
|
Following C/C++ tradition, let's start with the "hello, world". A C++
|
||||||
Function:</p>
|
Function:</p>
|
||||||
|
|||||||
@@ -3,31 +3,28 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title>Embedding</title>
|
<title>Embedding</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="iterators.html" title="Iterators">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.embedding"></a>Embedding</h2></div></div></div>
|
||||||
<a name="python.embedding"></a>Embedding</h2></div></div>
|
|
||||||
<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>
|
<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>
|
<p>
|
||||||
By now you should know how to use Boost.Python to call your C++ code from
|
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
|
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>
|
all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
|
||||||
<a name="embedding.building_embedded_programs"></a><h2>
|
<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>
|
<p>
|
||||||
To be able to use embedding in your programs, they have to be linked to
|
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>
|
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
|
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
|
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,
|
<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>
|
<p>
|
||||||
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory of
|
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
|
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) ;
|
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||||
</tt></pre>
|
</tt></pre>
|
||||||
<a name="embedding.getting_started"></a><h2>
|
<a name="embedding.getting_started"></a><h2>
|
||||||
<a name="id428846"></a>Getting started</h2>
|
<a name="id460605"></a>Getting started</h2>
|
||||||
<p>
|
<p>
|
||||||
Being able to build is nice, but there is nothing to build yet. Embedding
|
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
|
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>
|
(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="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="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
As you probably already know, objects in Python are reference-counted.
|
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.
|
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
|
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
|
<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.
|
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 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="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>
|
<p>
|
||||||
There are two ways in which a function in the Python/C API can return a
|
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
|
<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>
|
</td></tr></tbody>
|
||||||
</table></div>
|
</table></div>
|
||||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
<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>
|
<p>
|
||||||
To run Python code from C++ there is a family of functions in the API
|
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
|
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>
|
for interpreting the code. The possible values are:</p>
|
||||||
<div class="informaltable">
|
<div class="informaltable">
|
||||||
<h4>
|
<h4>
|
||||||
<a name="id429442"></a><span class="table-title">Start symbols</span>
|
<a name="id461201"></a><span class="table-title">Start symbols</span>
|
||||||
</h4>
|
</h4>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<colgroup>
|
<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
|
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>
|
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="using_the_interpreter.beyond_handles"></a><h2>
|
||||||
<a name="id429881"></a>Beyond handles</h2>
|
<a name="id461639"></a>Beyond handles</h2>
|
||||||
<p>
|
<p>
|
||||||
It's nice that <tt class="literal">handle</tt> manages the reference counting details for us, but
|
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
|
other than that it doesn't do much. Often we'd like to have a more useful
|
||||||
@@ -271,7 +266,7 @@ 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>
|
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt>
|
||||||
perform.</p>
|
perform.</p>
|
||||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||||
<a name="id430451"></a>Exception handling</h2>
|
<a name="id462209"></a>Exception handling</h2>
|
||||||
<p>
|
<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>
|
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
|
function returns a null pointer. Constructing a <tt class="literal">handle</tt> out of this null
|
||||||
@@ -301,8 +296,7 @@ To find out more about the Python exception that occurred, you need to use the
|
|||||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
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
|
<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
|
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">
|
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html%20standard" target="_top">exceptions</a>:</p>
|
||||||
standard 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">
|
<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">
|
{</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">
|
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">
|
||||||
@@ -320,7 +314,7 @@ standard exceptions</a>:</p>
|
|||||||
exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)</p>
|
exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)</p>
|
||||||
<p>
|
<p>
|
||||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception when it is constructed, you
|
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
|
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>
|
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">
|
<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">
|
"5/0"</span><span class="special">
|
||||||
|
|||||||
@@ -3,31 +3,28 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title> Exception Translation</title>
|
<title> Exception Translation</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.exception"></a> Exception Translation</h2></div></div></div>
|
||||||
<a name="python.exception"></a> Exception Translation</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
All C++ exceptions must be caught at the boundary with Python code. This
|
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
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title> Exposing Classes</title>
|
<title> Exposing Classes</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="functions.html" title="Functions">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.exposing"></a> Exposing Classes</h2></div></div></div>
|
||||||
<a name="python.exposing"></a> Exposing Classes</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="toc"><dl>
|
<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.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_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.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.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.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.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>
|
<dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||||
</dl></div>
|
</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">
|
>>></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>
|
'howdy'</span></tt></pre>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||||
<a name="python.constructors"></a>Constructors</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Our previous example didn't have any explicit constructors.
|
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
|
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>
|
Python RuntimeError exception.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
|
||||||
<a name="python.class_data_members"></a>Class Data Members</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Data members may also be exposed to Python so that they can be
|
Data members may also be exposed to Python so that they can be
|
||||||
accessed as attributes of the corresponding Python class. Each data
|
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>
|
</tt></pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.class_properties"></a>Class Properties</h3></div></div></div>
|
||||||
<a name="python.class_properties"></a>Class Properties</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
In C++, classes with public data members are usually frowned
|
In C++, classes with public data members are usually frowned
|
||||||
upon. Well designed classes that take advantage of encapsulation hide
|
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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.inheritance"></a>Inheritance</h3></div></div></div>
|
||||||
<a name="python.inheritance"></a>Inheritance</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
In the previous examples, we dealt with classes that are not polymorphic.
|
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
|
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>
|
Doing so, we get some things for free:</p>
|
||||||
<div class="orderedlist"><ol type="1">
|
<div class="orderedlist"><ol type="1">
|
||||||
<li>
|
<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>
|
||||||
<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>
|
</li>
|
||||||
</ol></div>
|
</ol></div>
|
||||||
<p>
|
<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
|
<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>
|
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
|
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
|
<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">
|
</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>
|
return_value_policy</span><span class="special"><</span><span class="identifier">manage_new_object</span><span class="special">>());</span></tt></pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
|
||||||
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
In this section, we shall learn how to make functions behave
|
In this section, we shall learn how to make functions behave polymorphically
|
||||||
polymorphically through virtual functions. Continuing our example, let us
|
through virtual functions. Continuing our example, let us add a virtual function
|
||||||
add a virtual function to our <tt class="literal">Base</tt> class:</p>
|
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">
|
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||||
{</span><span class="keyword">
|
{</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">
|
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>
|
};</span></tt></pre>
|
||||||
<p>
|
<p>
|
||||||
Since <tt class="literal">f</tt> is a pure virtual function, <tt class="literal">Base</tt> is now an abstract
|
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||||
class. Given an instance of our class, the free function <tt class="literal">call_f</tt>
|
design. In principle, it should be possible to expose the interface for a 3rd
|
||||||
calls some implementation of this virtual function in a concrete
|
party library without changing it. It is not ideal to add anything to our class
|
||||||
derived class:</p>
|
<tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when you have a virtual function that's going to be overridden in
|
||||||
<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>
|
Python and called polymorphically <span class="bold"><b>from C++</b></span>, we'll need to add some
|
||||||
<p>
|
scaffoldings to make things work properly. What we'll do is write a class
|
||||||
To allow this function to be implemented in a Python derived class, we
|
wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt> that will unintrusively hook into the virtual
|
||||||
need to create a class wrapper:</p>
|
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">
|
<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="identifier">
|
{</span><span class="keyword">
|
||||||
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">
|
int</span><span class="identifier"> f</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">
|
{</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">
|
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">
|
||||||
PyObject</span><span class="special">*</span><span class="identifier"> self</span><span class="special">;</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">
|
|
||||||
};</span></tt></pre>
|
};</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">
|
<div class="informaltable"><table class="table">
|
||||||
<colgroup><col></colgroup>
|
<colgroup><col></colgroup>
|
||||||
<tbody><tr><td>
|
<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>
|
correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||||
</td></tr></tbody>
|
</td></tr></tbody>
|
||||||
</table></div>
|
</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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
|
||||||
<a name="python.deriving_a_python_class"></a>Deriving a Python Class</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Continuing, we can derive from our base class Base in Python and override
|
We've seen in the previous section how classes with pure virtual functions are
|
||||||
the virtual function in Python. Before we can do that, we have to set up
|
wrapped using Boost.Python's <a href="../../../../v2//wrapper.html" target="_top">class wrapper</a>
|
||||||
our <tt class="literal">class_</tt> wrapper as:</p>
|
facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions instead, the
|
||||||
<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">
|
mechanism is a bit different.</p>
|
||||||
;</span></tt></pre>
|
|
||||||
<p>
|
<p>
|
||||||
Otherwise, we have to suppress the Base class' <tt class="literal">no_init</tt> by adding an
|
Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous section</a>, we
|
||||||
<tt class="literal"><span class="underline">_init</span>_()</tt> method to all our derived classes. <tt class="literal">no_init</tt> actually adds
|
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||||
an <tt class="literal"><span class="underline">_init</span>_</tt> method that raises a Python RuntimeError exception.</p>
|
Python classes derived from it. Our base class:</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>
|
|
||||||
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||||
{</span><span class="keyword">
|
{</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">
|
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>
|
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">
|
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special">
|
||||||
{</span><span class="keyword">
|
{</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">
|
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>
|
};</span></tt></pre>
|
||||||
<p>
|
<p>
|
||||||
and instead had a default implementation that returns <tt class="literal">0</tt>, as shown above,
|
We wrap it this way:</p>
|
||||||
we need to add a forwarding function that calls the <tt class="literal">Base</tt> default virtual
|
<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">
|
||||||
function <tt class="literal">f</tt> implementation:</p>
|
{</span><span class="keyword">
|
||||||
<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">
|
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special">
|
||||||
{</span><span class="identifier">
|
{</span><span class="keyword">
|
||||||
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">
|
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">
|
||||||
:</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">
|
return</span><span class="identifier"> f</span><span class="special">();</span><span class="comment"> // *note*
|
||||||
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">
|
</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">
|
||||||
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="keyword">
|
||||||
</span><span class="identifier"> PyObject</span><span class="special">*</span><span class="identifier"> self</span><span class="special">;</span><span class="special">
|
|
||||||
|
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>
|
};</span></tt></pre>
|
||||||
<p>
|
<p>
|
||||||
Then, Boost.Python needs to keep track of 1) the dispatch function <tt class="literal">f</tt> and
|
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
|
||||||
2) the forwarding function to its default implementation <tt class="literal">default_f</tt>.
|
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>
|
||||||
There's a special <tt class="literal">def</tt> function for this purpose. Here's how it is
|
<div class="informaltable"><table class="table">
|
||||||
applied to our example above:</p>
|
<colgroup><col></colgroup>
|
||||||
<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">
|
<tbody><tr><td>
|
||||||
.</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>
|
<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>
|
<p>
|
||||||
Note that we are allowing <tt class="literal">Base</tt> objects to be instantiated this time,
|
Finally, exposing:</p>
|
||||||
unlike before where we specifically defined the <tt class="literal">class_<Base></tt> with
|
<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">
|
||||||
<tt class="literal">no_init</tt>.</p>
|
.</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>
|
<p>
|
||||||
In Python, the results would be as expected:</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">
|
<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>
|
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">
|
<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>
|
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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<a name="class_operators_special_functions.python_operators"></a><h2>
|
<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>
|
<p>
|
||||||
C is well known for the abundance of operators. C++ extends this to the
|
C is well known for the abundance of operators. C++ extends this to the
|
||||||
extremes by allowing operator overloading. Boost.Python takes advantage of
|
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
|
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>
|
<tt class="literal">T</tt> instance when writing "self expressions".</p>
|
||||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
<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>
|
<p>
|
||||||
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python supports all of the
|
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
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title>Functions</title>
|
<title>Functions</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="object.html" title=" Object Interface">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.functions"></a>Functions</h2></div></div></div>
|
||||||
<a name="python.functions"></a>Functions</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="toc"><dl>
|
<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.call_policies">Call Policies</a></span></dt>
|
||||||
<dt><span class="section"><a href="functions.html#python.overloading">Overloading</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!
|
Namespaces are one honking great idea -- let's do more of those!
|
||||||
</tt></pre>
|
</tt></pre>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.call_policies"></a>Call Policies</h3></div></div></div>
|
||||||
<a name="python.call_policies"></a>Call Policies</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
In C++, we often deal with arguments and return types such as pointers
|
In C++, we often deal with arguments and return types such as pointers
|
||||||
and references. Such primitive types are rather, ummmm, low level and
|
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>
|
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||||
</ol></div>
|
</ol></div>
|
||||||
<a name="call_policies.call_policies"></a><h2>
|
<a name="call_policies.call_policies"></a><h2>
|
||||||
<a name="id422411"></a>Call Policies</h2>
|
<a name="id454162"></a>Call Policies</h2>
|
||||||
<p>
|
<p>
|
||||||
Call Policies may be used in situations such as the example detailed above.
|
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>
|
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>
|
</table></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.overloading"></a>Overloading</h3></div></div></div>
|
||||||
<a name="python.overloading"></a>Overloading</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
The following illustrates a scheme for manually wrapping an overloaded
|
The following illustrates a scheme for manually wrapping an overloaded
|
||||||
member functions. Of course, the same technique can be applied to wrapping
|
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>
|
.</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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
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
|
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>
|
</span></tt></pre>
|
||||||
<p>
|
<p>
|
||||||
Because of this, when wrapping C++ code, we had to resort to manual
|
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>
|
writing thin wrappers:</p>
|
||||||
<pre class="programlisting"><tt class="literal"><span class="comment">// write "thin wrappers"
|
<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">
|
</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>
|
</li>
|
||||||
</ul></div>
|
</ul></div>
|
||||||
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
<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>
|
<p>
|
||||||
Boost.Python now has a way to make it easier. For instance, given a function:</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">
|
<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>
|
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>
|
<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="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>
|
<p>
|
||||||
Objects here, objects there, objects here there everywhere. More frequently
|
Objects here, objects there, objects here there everywhere. More frequently
|
||||||
than anything else, we need to expose member functions of our classes to
|
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>
|
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads reference</a>
|
||||||
for details.</p>
|
for details.</p>
|
||||||
<a name="default_arguments.init_and_optional"></a><h2>
|
<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>
|
<p>
|
||||||
A similar facility is provided for class constructors, again, with
|
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,
|
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>
|
(optional arguments).</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
It was mentioned in passing in the previous section that
|
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>
|
<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
|
Notice though that we have a situation now where we have a minimum of zero
|
||||||
(0) arguments and a maximum of 3 arguments.</p>
|
(0) arguments and a maximum of 3 arguments.</p>
|
||||||
<a name="auto_overloading.manual_wrapping"></a><h2>
|
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||||
<a name="id425478"></a>Manual Wrapping</h2>
|
<a name="id457233"></a>Manual Wrapping</h2>
|
||||||
<p>
|
<p>
|
||||||
It is important to emphasize however that <span class="bold"><b>the overloaded functions must
|
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
|
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
|
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>
|
<p>
|
||||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
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
|
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
|
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
|
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
|
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
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title> Building Hello World</title>
|
<title> Building Hello World</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||||
<a name="python.hello"></a> Building Hello World</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<a name="hello.from_start_to_finish"></a><h2>
|
<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>
|
<p>
|
||||||
Now the first thing you'd want to do is to build the Hello World module and
|
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
|
try it for yourself in Python. In this section, we shall outline the steps
|
||||||
@@ -98,7 +95,7 @@ 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 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="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><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
|
||||||
<p>
|
<p>
|
||||||
Here is our minimalist Jamfile:</p>
|
Here is our minimalist Jamfile:</p>
|
||||||
@@ -131,7 +128,7 @@ Finally we declare our <tt class="literal">hello</tt> extension:</p>
|
|||||||
;
|
;
|
||||||
</tt></pre>
|
</tt></pre>
|
||||||
<a name="hello.running_bjam"></a><h2>
|
<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>
|
<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>
|
<div class="blockquote"><blockquote class="blockquote"><p>Start it up.</p></blockquote></div>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -3,31 +3,28 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title>Iterators</title>
|
<title>Iterators</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.iterators"></a>Iterators</h2></div></div></div>
|
||||||
<a name="python.iterators"></a>Iterators</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
In C++, and STL in particular, we see iterators everywhere. Python also has
|
In C++, and STL in particular, we see iterators everywhere. Python also has
|
||||||
iterators, but these are two very different beasts.</p>
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title> Object Interface</title>
|
<title> Object Interface</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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">
|
<link rel="next" href="embedding.html" title="Embedding">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.object"></a> Object Interface</h2></div></div></div>
|
||||||
<a name="python.object"></a> Object Interface</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="toc"><dl>
|
<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.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>
|
<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>
|
should minimize the learning curve significantly.</p>
|
||||||
<p><span class="inlinemediaobject"><img src="../images/python.png"></span></p>
|
<p><span class="inlinemediaobject"><img src="../images/python.png"></span></p>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the intricacies of dealing with
|
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
|
<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>
|
coder.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Boost.Python comes with a set of derived <tt class="literal">object</tt> types corresponding to
|
Boost.Python comes with a set of derived <tt class="literal">object</tt> types corresponding to
|
||||||
that of Python's:</p>
|
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">
|
<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>
|
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="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>
|
<p>
|
||||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt> may
|
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
|
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>
|
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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
At some point, we will need to get C++ values out of object instances. This
|
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>
|
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>
|
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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||||
<a name="python.enums"></a>Enums</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While
|
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
|
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">
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
<title> General Techniques</title>
|
<title> General Techniques</title>
|
||||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
<meta name="generator" content="DocBook XSL Stylesheets V1.65.1">
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
<link rel="home" href="../index.html" title="Chapter 1. python 1.0">
|
<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="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>
|
</head>
|
||||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
<table cellpadding="2" width="100%">
|
<table cellpadding="2" width="100%">
|
||||||
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></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="../../../../../../../index.htm">Home</a></td>
|
||||||
<td align="center"><a href="../libraries.html">Libraries</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="../../../../../../../people/people.htm">People</a></td>
|
||||||
<td align="center"><a href="../../../more/faq.htm">FAQ</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 align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spirit-nav">
|
<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>
|
<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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
<div><div><h2 class="title" style="clear: both">
|
<a name="python.techniques"></a> General Techniques</h2></div></div></div>
|
||||||
<a name="python.techniques"></a> General Techniques</h2></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="toc"><dl>
|
<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.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>
|
<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>
|
<p>
|
||||||
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</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="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
|
||||||
<a name="python.creating_packages"></a>Creating Packages</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
A Python package is a collection of modules that provide to the user a certain
|
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
|
functionality. If you're not familiar on how to create packages, a good
|
||||||
@@ -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>
|
>>></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>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
|
||||||
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
Thanks to Python's flexibility, you can easily add new methods to a class,
|
Thanks to Python's flexibility, you can easily add new methods to a class,
|
||||||
even after it was already created:</p>
|
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>
|
}</span></tt></pre>
|
||||||
<p>
|
<p>
|
||||||
If we are using the technique from the previous session,
|
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>
|
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>
|
<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>
|
the keyword support.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" lang="en">
|
<div class="section" lang="en">
|
||||||
<div class="titlepage">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<div><div><h3 class="title">
|
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
|
||||||
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
If you have ever exported a lot of classes, you know that it takes quite a good
|
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
|
time to compile the Boost.Python wrappers. Plus the memory consumption can
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
[/ QuickBook Document version 0.9 ]
|
[/ QuickBook Document version 0.9 ]
|
||||||
|
|
||||||
[def __note__ [$../images/note.png]]
|
[def __note__ [$images/note.png]]
|
||||||
[def __alert__ [$../images/alert.png]]
|
[def __alert__ [$images/alert.png]]
|
||||||
[def __tip__ [$../images/tip.png]]
|
[def __tip__ [$images/tip.png]]
|
||||||
[def :-) [$../images/smiley.png]]
|
[def :-) [$images/smiley.png]]
|
||||||
|
|
||||||
[section QuickStart]
|
[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
|
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
|
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:
|
After this brief ['bjam] tutorial, we should have built two DLLs:
|
||||||
|
|
||||||
* boost_python.dll
|
* boost_python.dll
|
||||||
@@ -189,7 +189,7 @@ Finally:
|
|||||||
|
|
||||||
We are again assuming that we are using Microsoft Visual C++ version 6. If
|
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
|
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.
|
further details.
|
||||||
|
|
||||||
It should be building now:
|
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:
|
Doing so, we get some things for free:
|
||||||
|
|
||||||
# Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
|
# Derived automatically inherits all of Base's Python methods
|
||||||
# [*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.
|
(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]:
|
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
|
[^return_value_policy<manage_new_object>] to instruct Python to adopt
|
||||||
the pointer to [^Base] and hold the instance in a new Python [^Base]
|
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
|
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
|
// Tell Python to take ownership of factory's result
|
||||||
def("factory", factory,
|
def("factory", factory,
|
||||||
return_value_policy<manage_new_object>());
|
return_value_policy<manage_new_object>());
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section Class Virtual Functions]
|
[section Class Virtual Functions]
|
||||||
|
|
||||||
In this section, we shall learn how to make functions behave
|
In this section, we shall learn how to make functions behave polymorphically
|
||||||
polymorphically through virtual functions. Continuing our example, let us
|
through virtual functions. Continuing our example, let us add a virtual function
|
||||||
add a virtual function to our [^Base] class:
|
to our [^Base] class:
|
||||||
|
|
||||||
struct Base
|
struct Base
|
||||||
{
|
{
|
||||||
|
virtual ~Base() {}
|
||||||
virtual int f() = 0;
|
virtual int f() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Since [^f] is a pure virtual function, [^Base] is now an abstract
|
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||||
class. Given an instance of our class, the free function [^call_f]
|
design. In principle, it should be possible to expose the interface for a 3rd
|
||||||
calls some implementation of this virtual function in a concrete
|
party library without changing it. It is not ideal to add anything to our class
|
||||||
derived 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(); }
|
struct BaseWrap : Base, wrapper<Base>
|
||||||
|
|
||||||
To allow this function to be implemented in a Python derived class, we
|
|
||||||
need to create a class wrapper:
|
|
||||||
|
|
||||||
struct BaseWrap : Base
|
|
||||||
{
|
{
|
||||||
BaseWrap(PyObject* self_)
|
int f()
|
||||||
: self(self_) {}
|
{
|
||||||
int f() { return call_method<int>(self, "f"); }
|
return this->get_override("f")();
|
||||||
PyObject* self;
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
[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
|
||||||
BaseWrap(PyObject* self_)
|
`return call<int>(this->get_override("f").ptr());`.]
|
||||||
: self(self_) {}
|
|
||||||
BaseWrap(PyObject* self_, Base const& copy)
|
BaseWrap's overridden virtual member function `f` in effect calls the
|
||||||
: Base(copy), self(self_) {}
|
corresponding method of the Python object through `get_override`.
|
||||||
int f() { return call_method<int>(self, "f"); }
|
|
||||||
int default_f() { return Base::f(); } // <<=== ***ADDED***
|
Finally, exposing `Base`:
|
||||||
PyObject* self;
|
|
||||||
};
|
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
|
[blurb __note__ [*member function and methods]\n\n Python, like
|
||||||
many object oriented languages uses the term [*methods]. Methods
|
many object oriented languages uses the term [*methods]. Methods
|
||||||
correspond roughly to C++'s [*member functions]]
|
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]
|
[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]
|
[section Virtual Functions with Default Implementations]
|
||||||
|
|
||||||
Recall that in the [@exposing.html#class_virtual_functions previous section], we
|
We've seen in the previous section how classes with pure virtual functions are
|
||||||
wrapped a class with a pure virtual function that we then implemented in
|
wrapped using Boost.Python's [@../../../v2//wrapper.html class wrapper]
|
||||||
C++ or Python classes derived from it. Our base class:
|
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
|
struct Base
|
||||||
{
|
{
|
||||||
@@ -628,33 +556,42 @@ not declared as pure virtual:
|
|||||||
|
|
||||||
struct Base
|
struct Base
|
||||||
{
|
{
|
||||||
|
virtual ~Base() {}
|
||||||
virtual int f() { return 0; }
|
virtual int f() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
and instead had a default implementation that returns [^0], as shown above,
|
We wrap it this way:
|
||||||
we need to add a forwarding function that calls the [^Base] default virtual
|
|
||||||
function [^f] implementation:
|
|
||||||
|
|
||||||
struct BaseWrap : Base
|
struct BaseWrap : Base, wrapper<Base>
|
||||||
{
|
{
|
||||||
BaseWrap(PyObject* self_)
|
int f()
|
||||||
: self(self_) {}
|
{
|
||||||
int f() { return call_method<int>(self, "f"); }
|
if (override f = this->get_override("f"))
|
||||||
int default_f() { return Base::f(); } // <<=== ***ADDED***
|
return f(); // *note*
|
||||||
PyObject* self;
|
return Base::f();
|
||||||
|
}
|
||||||
|
|
||||||
|
int default_f() { return this->Base::f(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
Then, Boost.Python needs to keep track of 1) the dispatch function [^f] and
|
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
|
||||||
2) the forwarding function to its default implementation [^default_f].
|
override for `f`. If none, then we call `Base::f()`.
|
||||||
There's a special [^def] function for this purpose. Here's how it is
|
|
||||||
applied to our example above:
|
|
||||||
|
|
||||||
class_<Base, BaseWrap, BaseWrap, boost::noncopyable>("Base")
|
[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());`.]
|
||||||
|
|
||||||
|
Finally, exposing:
|
||||||
|
|
||||||
|
class_<BaseWrap, boost::noncopyable>("Base")
|
||||||
.def("f", &Base::f, &BaseWrap::default_f)
|
.def("f", &Base::f, &BaseWrap::default_f)
|
||||||
|
;
|
||||||
|
|
||||||
Note that we are allowing [^Base] objects to be instantiated this time,
|
Take note that we expose both `&Base::f` and `&BaseWrap::default_f`.
|
||||||
unlike before where we specifically defined the [^class_<Base>] with
|
Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the
|
||||||
[^no_init].
|
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:
|
In Python, the results would be as expected:
|
||||||
|
|
||||||
@@ -675,16 +612,6 @@ Calling [^derived.f()]:
|
|||||||
>>> derived.f()
|
>>> derived.f()
|
||||||
42
|
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]
|
[endsect]
|
||||||
[section Class Operators/Special Functions]
|
[section Class Operators/Special Functions]
|
||||||
|
|
||||||
@@ -918,7 +845,7 @@ or more policies can be composed by chaining. Here's the general syntax:
|
|||||||
policy3<args...> > >
|
policy3<args...> > >
|
||||||
|
|
||||||
Here is the list of predefined call policies. A complete reference detailing
|
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]\n Ties lifetimes of the arguments
|
||||||
* [*with_custodian_and_ward_postcall]\n Ties lifetimes of the arguments and results
|
* [*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!
|
def("f", f); // defaults lost!
|
||||||
|
|
||||||
Because of this, when wrapping C++ code, we had to resort to manual
|
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:
|
writing thin wrappers:
|
||||||
|
|
||||||
// write "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());
|
.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.
|
for details.
|
||||||
|
|
||||||
[h2 init and optional]
|
[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
|
It is important to emphasize however that [*the overloaded functions must
|
||||||
have a common sequence of initial arguments]. Otherwise, our scheme above
|
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
|
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
|
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||||
automatic wrapping through [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] and
|
automatic wrapping through [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] and
|
||||||
its sister, [^BOOST_PYTHON_FUNCTION_OVERLOADS]. Following up on our example
|
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
|
first 4 overload functins have a common sequence of initial arguments, we
|
||||||
can use [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] to automatically wrap the
|
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
|
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
|
feel. Boost.Python C++ [^object]s are as close as possible to Python. This
|
||||||
should minimize the learning curve significantly.
|
should minimize the learning curve significantly.
|
||||||
|
|
||||||
[$../images/python.png]
|
[$images/python.png]
|
||||||
|
|
||||||
[section Basic Interface]
|
[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
|
[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
|
associated global Python object which controls the Python namespace in
|
||||||
which new extension classes and wrapped functions will be defined as
|
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
|
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
|
in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
|
||||||
variants are called [^boost_python.lib] (for release builds) and
|
variants are called [^boost_python.lib] (for release builds) and
|
||||||
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
||||||
you probably haven't built Boost.Python yet. See [@../../../../building.html
|
you probably haven't built Boost.Python yet. See
|
||||||
Building and Testing] on how to do this.
|
[@../../../building.html Building and Testing] on how to do this.
|
||||||
|
|
||||||
Python's static link library can be found in the [^/libs] subdirectory of
|
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
|
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
|
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
|
[@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.
|
messy and especially hard to get right in the presence of C++ exceptions.
|
||||||
Fortunately Boost.Python provides the [@../../v2/handle.html handle] and
|
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
|
||||||
[@../../../../v2/object.html object] class templates to automate the process.
|
[@../../../v2/object.html object] class templates to automate the process.
|
||||||
|
|
||||||
[h2 Reference-counting handles and objects]
|
[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
|
For a function returning a ['borrowed reference] we'll have to tell the
|
||||||
[^handle] that the [^PyObject*] is borrowed with the aptly named
|
[^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.
|
returning borrowed references are PyImport_AddModule and PyModule_GetDict.
|
||||||
The former returns a reference to an already imported module, the latter
|
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
|
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||||
@@ -1624,7 +1551,7 @@ perform.
|
|||||||
|
|
||||||
If an exception occurs in the execution of some Python code, the PyRun_String
|
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
|
function returns a null pointer. Constructing a [^handle] out of this null
|
||||||
pointer throws [@../../../../v2/errors.html#error_already_set-spec error_already_set],
|
pointer throws [@../../../v2/errors.html#error_already_set-spec error_already_set],
|
||||||
so basically, the Python exception is automatically translated into a
|
so basically, the Python exception is automatically translated into a
|
||||||
C++ exception when using [^handle]:
|
C++ exception when using [^handle]:
|
||||||
|
|
||||||
@@ -1671,7 +1598,7 @@ standard exceptions]:
|
|||||||
exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
|
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
|
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
|
can use the [@../../../v2/handle.html#allow_null-spec allow_null] function in the same
|
||||||
way you'd use borrowed:
|
way you'd use borrowed:
|
||||||
|
|
||||||
handle<> result((allow_null(PyRun_String(
|
handle<> result((allow_null(PyRun_String(
|
||||||
@@ -1980,7 +1907,7 @@ we have a class [^point] in C++:
|
|||||||
}
|
}
|
||||||
|
|
||||||
If we are using the technique from the previous session,
|
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]:
|
into [^geom/__init__.py]:
|
||||||
|
|
||||||
from _geom import *
|
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
|
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.
|
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
|
take a look at the [^--multiple] option, that generates the wrappers in
|
||||||
various files as demonstrated here.]
|
various files as demonstrated here.]
|
||||||
|
|
||||||
[blurb __note__ This method is useful too if you are getting the error message
|
[blurb __note__ This method is useful too if you are getting the error message
|
||||||
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
|
['"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]
|
||||||
[endsect] [/ General Techniques]
|
[endsect] [/ General Techniques]
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ with every boost distribution: <emphasis role="bold">bjam</emphasis>.</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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/>
|
<para/>
|
||||||
|
|
||||||
Besides bjam, there are of course other ways to get your module built.
|
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>
|
<para>
|
||||||
We shall skip over the details. Our objective will be to simply create the
|
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
|
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>
|
After this brief <emphasis>bjam</emphasis> tutorial, we should have built two DLLs:</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -222,7 +222,7 @@ appropriately.</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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>
|
even if that's the version you have.</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -241,7 +241,7 @@ Finally:</para>
|
|||||||
<para>
|
<para>
|
||||||
We are again assuming that we are using Microsoft Visual C++ version 6. If
|
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
|
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>
|
further details.</para>
|
||||||
<para>
|
<para>
|
||||||
It should be building now:</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>
|
Doing so, we get some things for free:</para>
|
||||||
<orderedlist>
|
<orderedlist>
|
||||||
<listitem>
|
<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>
|
</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>
|
</listitem>
|
||||||
</orderedlist><para>
|
</orderedlist><para>
|
||||||
Now, we shall expose the C++ free functions <literal>b</literal> and <literal>d</literal> and <literal>factory</literal>:</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
|
<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>
|
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
|
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>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
<phrase role="comment">// Tell Python to take ownership of factory's result
|
<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">
|
<section id="python.class_virtual_functions">
|
||||||
<title>Class Virtual Functions</title>
|
<title>Class Virtual Functions</title>
|
||||||
<para>
|
<para>
|
||||||
In this section, we shall learn how to make functions behave
|
In this section, we shall learn how to make functions behave polymorphically
|
||||||
polymorphically through virtual functions. Continuing our example, let us
|
through virtual functions. Continuing our example, let us add a virtual function
|
||||||
add a virtual function to our <literal>Base</literal> class:</para>
|
to our <literal>Base</literal> class:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||||
{</phrase><phrase role="keyword">
|
{</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">
|
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>
|
};</phrase>
|
||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Since <literal>f</literal> is a pure virtual function, <literal>Base</literal> is now an abstract
|
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||||
class. Given an instance of our class, the free function <literal>call_f</literal>
|
design. In principle, it should be possible to expose the interface for a 3rd
|
||||||
calls some implementation of this virtual function in a concrete
|
party library without changing it. It is not ideal to add anything to our class
|
||||||
derived class:</para>
|
<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>
|
<programlisting>
|
||||||
<literal>
|
<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>
|
<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">
|
||||||
</literal>
|
{</phrase><phrase role="keyword">
|
||||||
</programlisting>
|
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special">
|
||||||
<para>
|
{</phrase><phrase role="keyword">
|
||||||
To allow this function to be implemented in a Python derived class, we
|
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">
|
||||||
need to create a class wrapper:</para>
|
}</phrase><phrase role="special">
|
||||||
<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>
|
};</phrase>
|
||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</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">
|
<informaltable frame="all">
|
||||||
<?dbhtml table-width="74%" ?>
|
<?dbhtml table-width="74%" ?>
|
||||||
<tgroup cols="1">
|
<tgroup cols="1">
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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/>
|
<para/>
|
||||||
Python, like
|
Python, like
|
||||||
many object oriented languages uses the term <emphasis role="bold">methods</emphasis>. Methods
|
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>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</informaltable>
|
</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>
|
||||||
<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">
|
<section id="python.virtual_functions_with_default_implementations">
|
||||||
<title>Virtual Functions with Default Implementations</title>
|
<title>Virtual Functions with Default Implementations</title>
|
||||||
<para>
|
<para>
|
||||||
Recall that in the <ulink url="exposing.html#class_virtual_functions">previous section</ulink>, we
|
We've seen in the previous section how classes with pure virtual functions are
|
||||||
wrapped a class with a pure virtual function that we then implemented in
|
wrapped using Boost.Python's <ulink url="../../../v2//wrapper.html">class wrapper</ulink>
|
||||||
C++ or Python classes derived from it. Our base class:</para>
|
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>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||||
@@ -812,41 +708,63 @@ not declared as pure virtual:</para>
|
|||||||
<literal>
|
<literal>
|
||||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
|
||||||
{</phrase><phrase role="keyword">
|
{</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">
|
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>
|
};</phrase>
|
||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
and instead had a default implementation that returns <literal>0</literal>, as shown above,
|
We wrap it this way:</para>
|
||||||
we need to add a forwarding function that calls the <literal>Base</literal> default virtual
|
|
||||||
function <literal>f</literal> implementation:</para>
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</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="identifier">
|
{</phrase><phrase role="keyword">
|
||||||
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">
|
int</phrase><phrase role="identifier"> f</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">
|
{</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">
|
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">
|
||||||
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***
|
return</phrase><phrase role="identifier"> f</phrase><phrase role="special">();</phrase><phrase role="comment"> // *note*
|
||||||
</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"> 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>
|
};</phrase>
|
||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Then, Boost.Python needs to keep track of 1) the dispatch function <literal>f</literal> and
|
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
|
||||||
2) the forwarding function to its default implementation <literal>default_f</literal>.
|
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>
|
||||||
There's a special <literal>def</literal> function for this purpose. Here's how it is
|
<informaltable frame="all">
|
||||||
applied to our example above:</para>
|
<?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>
|
<programlisting>
|
||||||
<literal>
|
<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 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><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>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Note that we are allowing <literal>Base</literal> objects to be instantiated this time,
|
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>.
|
||||||
unlike before where we specifically defined the <literal>class_<Base></literal> with
|
Boost.Python needs to keep track of 1) the dispatch function <literal>f</literal> and 2) the
|
||||||
<literal>no_init</literal>.</para>
|
forwarding function to its default implementation <literal>default_f</literal>. There's a
|
||||||
|
special <literal>def</literal> function for this purpose.</para>
|
||||||
<para>
|
<para>
|
||||||
In Python, the results would be as expected:</para>
|
In Python, the results would be as expected:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@@ -875,22 +793,6 @@ Calling <literal>derived.f()</literal>:</para>
|
|||||||
42</phrase>
|
42</phrase>
|
||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</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>
|
||||||
<section id="python.class_operators_special_functions">
|
<section id="python.class_operators_special_functions">
|
||||||
<title>Class Operators/Special Functions</title>
|
<title>Class Operators/Special Functions</title>
|
||||||
@@ -966,7 +868,7 @@ Need we say more?</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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.
|
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>
|
<literal>operator<<</literal> is used by the method defined by def(str(self)).</entry>
|
||||||
</row>
|
</row>
|
||||||
@@ -1178,7 +1080,7 @@ or more policies can be composed by chaining. Here's the general syntax:</para>
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Here is the list of predefined call policies. A complete reference detailing
|
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>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<emphasis role="bold">with_custodian_and_ward</emphasis><para/>
|
<emphasis role="bold">with_custodian_and_ward</emphasis><para/>
|
||||||
@@ -1211,7 +1113,7 @@ Boost.Python v1 approach
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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/>
|
<para/>
|
||||||
|
|
||||||
"Explicit is better than implicit"<para/>
|
"Explicit is better than implicit"<para/>
|
||||||
@@ -1308,7 +1210,7 @@ to retrieve the default arguments:</para>
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Because of this, when wrapping C++ code, we had to resort to manual
|
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>
|
writing thin wrappers:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
@@ -1401,7 +1303,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
|
|||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<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>
|
for details.</para>
|
||||||
<anchor id="default_arguments.init_and_optional" /><bridgehead renderas="sect2">init and optional</bridgehead><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
|
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
|
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
|
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
|
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>
|
<para>
|
||||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||||
automatic wrapping through <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> 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
|
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
|
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
|
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
|
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
|
feel. Boost.Python C++ <literal>object</literal>s are as close as possible to Python. This
|
||||||
should minimize the learning curve significantly.</para>
|
should minimize the learning curve significantly.</para>
|
||||||
<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">
|
<section id="python.basic_interface">
|
||||||
<title>Basic Interface</title>
|
<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>
|
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>
|
in Python, which is useful since there's no easy way to do that in std C++.</para>
|
||||||
<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>
|
of most of Python's mutable types make copies, just as in Python.</para>
|
||||||
<para>
|
<para>
|
||||||
Python:</para>
|
Python:</para>
|
||||||
@@ -1721,7 +1623,7 @@ if</phrase><phrase role="special"> (</phrase><phrase role="identifier">x</phrase
|
|||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<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>
|
facility in fact solves the mutable copying problem:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
@@ -1765,12 +1667,12 @@ associated with the C++ type passed as its first parameter.</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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/>
|
<para/>
|
||||||
The scope is a class that has an
|
The scope is a class that has an
|
||||||
associated global Python object which controls the Python namespace in
|
associated global Python object which controls the Python namespace in
|
||||||
which new extension classes and wrapped functions will be defined as
|
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>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</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
|
<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,
|
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
|
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>
|
<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
|
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>
|
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
|
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
|
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,
|
<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
|
you probably haven't built Boost.Python yet. See
|
||||||
Building">and Testing</ulink> on how to do this.</para>
|
<ulink url="../../../building.html">Building and Testing</ulink> on how to do this.</para>
|
||||||
<para>
|
<para>
|
||||||
Python's static link library can be found in the <literal>/libs</literal> subdirectory of
|
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
|
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
|
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
|
<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.
|
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
|
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>
|
<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>
|
<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
|
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
|
<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>
|
<para>
|
||||||
For a function returning a <emphasis>borrowed reference</emphasis> we'll have to tell the
|
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
|
<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>.
|
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
|
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
|
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||||
@@ -1915,7 +1817,7 @@ discuss in the next section.</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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/>
|
<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
|
This should create a file called 'hello.txt' in the current directory
|
||||||
containing a phrase that is well-known in programming circles.</para>
|
containing a phrase that is well-known in programming circles.</para>
|
||||||
<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
|
(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
|
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>
|
you want to be a Dr. Frankenstein, always wrap <literal>PyObject*</literal>s in <literal>handle</literal>s.</para>
|
||||||
@@ -2042,14 +1944,14 @@ int</phrase><phrase role="identifier"> five_squared</phrase><phrase role="specia
|
|||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<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
|
<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>
|
take into account the different functions that <literal>object</literal> and <literal>handle</literal>
|
||||||
perform.</para>
|
perform.</para>
|
||||||
<anchor id="using_the_interpreter.exception_handling" /><bridgehead renderas="sect2">Exception handling</bridgehead><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>
|
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
|
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>,
|
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
|
so basically, the Python exception is automatically translated into a
|
||||||
C++ exception when using <literal>handle</literal>:</para>
|
C++ exception when using <literal>handle</literal>:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@@ -2079,8 +1981,8 @@ To find out more about the Python exception that occurred, you need to use the
|
|||||||
of the Python/C API in your catch-statement. This can be as simple as calling
|
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
|
<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
|
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">
|
exception with those of the <ulink url="http://www.python.org/doc/api/standardExceptions.html
|
||||||
standard exceptions</ulink>:</para>
|
standard">exceptions</ulink>:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
<phrase role="keyword">catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_already_set</phrase><phrase role="special">)</phrase><phrase role="special">
|
<phrase role="keyword">catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_already_set</phrase><phrase role="special">)</phrase><phrase role="special">
|
||||||
@@ -2102,7 +2004,7 @@ standard exceptions</ulink>:</para>
|
|||||||
exception handling functions listed <ulink url="http://www.python.org/doc/api/exceptionHandling.html">here</ulink>.)</para>
|
exception handling functions listed <ulink url="http://www.python.org/doc/api/exceptionHandling.html">here</ulink>.)</para>
|
||||||
<para>
|
<para>
|
||||||
If you'd rather not have <literal>handle</literal> throw a C++ exception when it is constructed, you
|
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
|
can use the <ulink url="../../../v2/handle.html#allow_null-spec">allow_null</ulink> function in the same
|
||||||
way you'd use borrowed:</para>
|
way you'd use borrowed:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
@@ -2325,7 +2227,7 @@ Compiling these files will generate the following Python extensions:
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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
|
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>
|
Unix and <literal>.dll</literal> for Windows, works just as well.</entry>
|
||||||
</row>
|
</row>
|
||||||
@@ -2477,7 +2379,7 @@ A</phrase><phrase role="identifier"> C</phrase><phrase role="identifier"> instan
|
|||||||
</literal>
|
</literal>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<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>
|
<para>
|
||||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||||
we have a class <literal>point</literal> in C++:</para>
|
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>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
If we are using the technique from the previous session,
|
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>
|
into <literal>geom/<emphasis role="underline">_init</emphasis>_.py</literal>:</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<literal>
|
<literal>
|
||||||
@@ -2643,7 +2545,7 @@ the compilation of a single cpp, instead of the entire wrapper code.</para>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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
|
take a look at the <literal>--multiple</literal> option, that generates the wrappers in
|
||||||
various files as demonstrated here.</entry>
|
various files as demonstrated here.</entry>
|
||||||
</row>
|
</row>
|
||||||
@@ -2656,9 +2558,9 @@ various files as demonstrated here.</entry>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<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
|
<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>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
|
|||||||
@@ -158,6 +158,6 @@ documentation).
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
||||||
|
|
||||||
<td>An MPL unary <a href=
|
<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>
|
Class</a> used produce the "preliminary" result object.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@@ -141,8 +141,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell and distribute this software is
|
<p>Permission to copy, use, modify, sell and distribute this software is
|
||||||
granted provided this copyright notice appears in all copies. This
|
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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ type.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -229,6 +229,6 @@ worth doing anything about it.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -303,6 +303,6 @@ to these issues will probably have to be formalized before long.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -144,13 +144,7 @@ instances of the associated Python type will be considered a match.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
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>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ C++ function return type.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -126,8 +126,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -190,8 +190,7 @@ BOOST_PYTHON_MODULE(xxx)
|
|||||||
<p>Revised 01 August, 2003</p>
|
<p>Revised 01 August, 2003</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||||
Rights Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,6 @@
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -77,6 +77,6 @@ double apply2(PyObject* func, double x, double y)
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -152,8 +152,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -245,8 +245,7 @@ void apply(PyObject* callable, X& x)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -730,7 +730,7 @@ class_& enable_pickling();
|
|||||||
<h3><a name="bases-spec"></a>Class template
|
<h3><a name="bases-spec"></a>Class template
|
||||||
<code>bases<T1, T2,</code>...<code>TN></code></h3>
|
<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>
|
which can be used in <code>class_<</code>...<code>></code>
|
||||||
instantiations indicate a list of base classes.</p>
|
instantiations indicate a list of base classes.</p>
|
||||||
|
|
||||||
@@ -794,8 +794,7 @@ class_<Derived, bases<Base> >("Derived");
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -146,8 +146,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE_INIT(data_members_example)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -182,8 +182,7 @@ BOOST_PYTHON_MODULE(def_test)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -132,4 +132,4 @@ BOOST_PYTHON_MODULE(my_ext)
|
|||||||
</p>
|
</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
|
<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>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -143,8 +143,7 @@ dict swap_object_dict(object target, dict d)
|
|||||||
<p>Revised 30 September, 2002</p>
|
<p>Revised 30 September, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -225,8 +225,7 @@ TypeError: bad argument type for built-in operation
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void handle_exception() throw();
|
|||||||
<dl class="handle_exception-semantics">
|
<dl class="handle_exception-semantics">
|
||||||
<dt><b>Requires:</b> The first form requires that the expression
|
<dt><b>Requires:</b> The first form requires that the expression
|
||||||
<code><a href=
|
<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
|
is valid. The second form requires that a C++ exception is currently
|
||||||
being handled (see section 15.1 in the C++ standard).</dt>
|
being handled (see section 15.1 in the C++ standard).</dt>
|
||||||
|
|
||||||
@@ -280,8 +280,7 @@ same_name2(PyObject* args, PyObject* keywords)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -141,8 +141,7 @@ BOOST_PYTHON_MODULE(exception_translator_ext)
|
|||||||
<p>Revised 03 October, 2002</p>
|
<p>Revised 03 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -223,8 +223,7 @@ BOOST_PYTHON_MODULE(extract_ext)
|
|||||||
<p>Revised 15 November, 2002</p>
|
<p>Revised 15 November, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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
|
<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>
|
much memory! What can I do to make it faster?</a></h2>
|
||||||
<p>
|
<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.
|
>Reducing Compiling Time</a> section in the tutorial.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
|
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
|
||||||
<p>
|
<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.
|
>Creating Packages</a> section in the tutorial.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -878,7 +878,6 @@ BOOST_PYTHON_MODULE(custom_string)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||||
Rights Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -362,5 +362,5 @@
|
|||||||
|
|
||||||
<p class="c3">© Copyright <a href=
|
<p class="c3">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
"../../../../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
|
<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>
|
||||||
|
|
||||||
<p class="c4">© Copyright <a href=
|
<p class="c4">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||||
Reserved.</p>
|
.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace boost { namespace python
|
|||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
</pre>
|
</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
|
metafunction</a>" that is inspected by Boost.Python to determine how
|
||||||
wrapped classes can be constructed.</p>
|
wrapped classes can be constructed.</p>
|
||||||
|
|
||||||
@@ -215,8 +215,8 @@ BOOST_PYTHON_MODULE(back_references)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="c3">© Copyright <a href=
|
<p class="c3">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||||
Reserved.</p>
|
.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -284,5 +284,5 @@ namespace boost
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
<i>unspecified</i><code>,</code>...<code>Tn</code> =
|
||||||
<i>unspecified</i><code>></code></h3>
|
<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>
|
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
|
functions. Only the last <code>T</code><i><small>i</small></i> supplied
|
||||||
may be an instantiation of <a href=
|
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>...<code>Tn</code> =
|
||||||
<i>unspecified</i><code>></code></h3>
|
<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>
|
can be used to specify the optional arguments to an <code>__init__</code>
|
||||||
function.</p>
|
function.</p>
|
||||||
|
|
||||||
@@ -242,8 +242,7 @@ class_<X>("X", "This is X's docstring.",
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||||
<meta http-equiv="Content-Type" content=
|
<meta http-equiv="Content-Type" content=
|
||||||
"text/html; charset=iso-8859-1">
|
"text/html; charset=iso-8859-1">
|
||||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||||
|
|
||||||
<title>Boost.Python - <boost/python/instance_holder.hpp></title>
|
<title>Boost.Python - <boost/python/instance_holder.hpp></title>
|
||||||
|
</head>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
p.c4 {font-style: italic}
|
p.c4 {font-style: italic}
|
||||||
span.c3 {color: #ff0000}
|
span.c3 {color: #ff0000}
|
||||||
@@ -13,6 +18,7 @@
|
|||||||
h1.c1 {text-align: center}
|
h1.c1 {text-align: center}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<body link="#0000ff" vlink="#800080">
|
||||||
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
||||||
summary="header">
|
summary="header">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -204,6 +210,7 @@ struct pointer_holder : instance_holder
|
|||||||
|
|
||||||
|
|
||||||
<p class="c4">© Copyright <a href=
|
<p class="c4">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.
|
||||||
Rights Reserved.
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
@@ -380,7 +380,8 @@ BOOST_PYTHON_MODULE(demo)
|
|||||||
<dt><code><a href=
|
<dt><code><a href=
|
||||||
"../../test/iterator.py">libs/python/test/input_iterator.py</a></code></dt>
|
"../../test/iterator.py">libs/python/test/input_iterator.py</a></code></dt>
|
||||||
|
|
||||||
<dd>
|
</dl>
|
||||||
|
<hr>
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||||
13 November, 2002
|
13 November, 2002
|
||||||
@@ -388,10 +389,7 @@ BOOST_PYTHON_MODULE(demo)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Rights Reserved.</i></p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -133,8 +133,7 @@ long zeroes(list l)
|
|||||||
<p>Revised 1 October, 2002</p>
|
<p>Revised 1 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -110,8 +110,7 @@ python::long_ fact(long n)
|
|||||||
<p>Revised 1 October, 2002</p>
|
<p>Revised 1 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -292,8 +292,7 @@ BOOST_PYTHON_MODULE(noddy_cache)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ template <class F, class Policies, class Keywords, class Signature>
|
|||||||
arguments of the resulting function.
|
arguments of the resulting function.
|
||||||
<li>If <code>Signature</code>
|
<li>If <code>Signature</code>
|
||||||
is supplied, it should be an instance of an <a
|
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
|
sequence</a> representing the function's return type followed by
|
||||||
its argument types. Pass a <code>Signature</code> when wrapping
|
its argument types. Pass a <code>Signature</code> when wrapping
|
||||||
function object types whose signatures can't be deduced, or when
|
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.
|
<dt><b>Requires:</b> <code>T</code> is a class type.
|
||||||
<code>Policies</code> is a model of <a href=
|
<code>Policies</code> is a model of <a href=
|
||||||
"CallPolicies.html">CallPolicies</a>. <code>ArgList</code> is an <a
|
"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
|
types (<i>A1, A2,... AN</i>) such that if
|
||||||
<code>a1, a2</code>... <code>aN</code> are objects of type
|
<code>a1, a2</code>... <code>aN</code> are objects of type
|
||||||
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
||||||
@@ -201,8 +201,7 @@ BOOST_PYTHON_MODULE(make_function_test)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -104,5 +104,5 @@ RuntimeError: Unidentifiable C++ Exception
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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>Revised 03 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -927,8 +927,7 @@ object sum_items(object seq)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -900,8 +900,7 @@ BOOST_PYTHON_MODULE(demo)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ struct X
|
|||||||
Y inner;
|
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)
|
BOOST_PYTHON_MODULE(args_ext)
|
||||||
{
|
{
|
||||||
@@ -205,7 +205,7 @@ BOOST_PYTHON_MODULE(args_ext)
|
|||||||
|
|
||||||
class_<X>("X", "This is X's docstring")
|
class_<X>("X", "This is X's docstring")
|
||||||
.def("f1", &X::f,
|
.def("f1", &X::f,
|
||||||
X_f_overloads(
|
f_member_overloads(
|
||||||
args("x", "y", "z"), "f's docstring"
|
args("x", "y", "z"), "f's docstring"
|
||||||
)[return_internal_reference<>()]
|
)[return_internal_reference<>()]
|
||||||
)
|
)
|
||||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE(args_ext)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,6 @@
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ class we make all instances pickleable:
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
See also the
|
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.
|
>tutorial section</a> on injecting additional methods from Python.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
@@ -133,8 +133,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -112,5 +112,5 @@ BOOST_PYTHON_MODULE(pointee_demo)
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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
|
<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>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
13 November, 2002
|
13 November, 2002
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -109,8 +109,7 @@ Python:
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -96,24 +96,29 @@
|
|||||||
|
|
||||||
<h2><a name="high_level">High Level Components</a></h2>
|
<h2><a name="high_level">High Level Components</a></h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
<dl>
|
|
||||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="class.html#classes">Classes</a></dt>
|
<dt><a href="class.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
<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#bases-spec">bases</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="def.html">def.hpp</a></dt>
|
<dt><a href="def.html">def.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="def.html#functions">Functions</a></dt>
|
<dt><a href="def.html#functions">Functions</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt><a href="def.html#def-spec">def</a></dt>
|
<dt><a href="def.html#def-spec">def</a></dt>
|
||||||
@@ -121,16 +126,21 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||||
@@ -138,35 +148,45 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
"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>
|
"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>
|
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
"exception_translator.html#functions">Functions</a></dt>
|
"exception_translator.html#functions">Functions</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
@@ -175,29 +195,39 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="init.html">init.hpp</a></dt>
|
<dt><a href="init.html">init.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="init.html#classes">Classes</a></dt>
|
<dt><a href="init.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="init.html#init-spec">init</a></dt>
|
<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#optional-spec">optional</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
<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#iterators-spec">iterators</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||||
@@ -205,10 +235,13 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="module.html">module.hpp</a></dt>
|
<dt><a href="module.html">module.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="module.html#macros">Macros</a></dt>
|
<dt><a href="module.html#macros">Macros</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href=
|
<dt><a href=
|
||||||
@@ -217,18 +250,25 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
<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#other-spec">other</a></dt>
|
||||||
|
|
||||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||||
@@ -236,10 +276,13 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="index">
|
<dl class="index">
|
||||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||||
@@ -247,7 +290,23 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
|
||||||
|
<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>
|
||||||
|
|
||||||
<h2><a name="object_wrappers">Object Wrappers</a></h2>
|
<h2><a name="object_wrappers">Object Wrappers</a></h2>
|
||||||
|
|
||||||
@@ -357,6 +416,7 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href="slice.html">slice.hpp</a></dt>
|
<dt><a href="slice.html">slice.hpp</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
@@ -978,22 +1038,24 @@
|
|||||||
|
|
||||||
<h2><a name="topics">Topics</a></h2>
|
<h2><a name="topics">Topics</a></h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><a href="callbacks.html">Calling Python Functions and
|
||||||
|
Methods</a></dt>
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><a href="callbacks.html">Calling Python Functions and Methods</a></dt>
|
|
||||||
<dt><a href="pickle.html">Pickle Support</a><br>
|
<dt><a href="pickle.html">Pickle Support</a><br>
|
||||||
<a href="indexing.html">Indexing Support</a></dt>
|
<a href="indexing.html">Indexing Support</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--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>
|
||||||
|
|
||||||
<p class="c3">© Copyright <a href=
|
<p class="c3">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002
|
||||||
Reserved.</p>
|
.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,7 @@ BOOST_PYTHON_MODULE(singleton)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ BOOST_PYTHON_MODULE(return_self_ext)
|
|||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> and Nikolay
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> and Nikolay
|
||||||
Mladenov 2003. All Rights Reserved.</i></p>
|
Mladenov 2003. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -220,8 +220,7 @@ BOOST_PYTHON_MODULE(internal_refs)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -158,8 +158,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -163,8 +163,7 @@ BOOST_PYTHON_MODULE(nested)
|
|||||||
<p>Revised 09 October, 2002</p>
|
<p>Revised 09 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -228,8 +228,7 @@ str remove_angle_brackets(str x)
|
|||||||
<p>Revised 3 October, 2002</p>
|
<p>Revised 3 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -197,8 +197,7 @@ BOOST_PYTHON_MODULE(to_python_converter)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -190,5 +190,5 @@ struct reference_existing_object
|
|||||||
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<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
|
<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>Revised 03 October, 2002</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||||
|
|
||||||
<title>Boost.Python - <boost/python/type_id.hpp></title>
|
<title>Boost.Python - <boost/python/type_id.hpp></title>
|
||||||
<style type="text/css">
|
|
||||||
|
<style type="text/css">
|
||||||
p.c4 {font-style: italic}
|
p.c4 {font-style: italic}
|
||||||
span.c3 {color: #ff0000}
|
span.c3 {color: #ff0000}
|
||||||
h2.c2 {text-align: center}
|
h2.c2 {text-align: center}
|
||||||
@@ -31,39 +32,41 @@
|
|||||||
<h2>Contents</h2>
|
<h2>Contents</h2>
|
||||||
|
|
||||||
<dl class="page-index">
|
<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>
|
<dd>
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt><a href="#type_info-spec">Class
|
<dt><a href="#type_info-spec">Class <code>type_info</code></a></dt>
|
||||||
<code>type_info</code></a>
|
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt><a href="#type_info-spec-synopsis">Class
|
<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
|
<dt><a href="#type_infospec-ctors">Class <code>type_info</code>
|
||||||
<code>type_info</code> constructor</a>
|
constructor</a></dt>
|
||||||
|
|
||||||
<dt><a href="#type_infospec-comparisons">Class
|
<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
|
<dt><a href="#type_infospec-observers">Class
|
||||||
<code>type_info</code> observer functions</a>
|
<code>type_info</code> observer functions</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
</dd>
|
||||||
|
|
||||||
<dt><a href="#functions">Functions</a>
|
<dt><a href="#functions">Functions</a></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt><a href="#type_id-spec">type_id</a>
|
<dt><a href="#type_id-spec">type_id</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
</dd>
|
||||||
|
|
||||||
<dt><a href="#examples">Example</a>
|
<dt><a href="#examples">Example</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
@@ -71,9 +74,9 @@
|
|||||||
|
|
||||||
<p><code><boost/python/type_id.hpp></code> provides types and
|
<p><code><boost/python/type_id.hpp></code> provides types and
|
||||||
functions for runtime type identification like those of of
|
functions for runtime type identification like those of of
|
||||||
<code><typeinfo></code>. It exists mostly to work around
|
<code><typeinfo></code>. It exists mostly to work around certain
|
||||||
certain compiler bugs and platform-dependent interactions with
|
compiler bugs and platform-dependent interactions with shared
|
||||||
shared libraries.
|
libraries.</p>
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
<h2><a name="classes"></a>Classes</h2>
|
||||||
|
|
||||||
@@ -81,15 +84,13 @@
|
|||||||
|
|
||||||
<p><code>type_info</code> instances identify a type. As
|
<p><code>type_info</code> instances identify a type. As
|
||||||
<code>std::type_info</code> is specified to (but unlike its
|
<code>std::type_info</code> is specified to (but unlike its
|
||||||
implementation in some compilers),
|
implementation in some compilers), <code>boost::python::type_info</code>
|
||||||
<code>boost::python::type_info</code> never represents top-level
|
never represents top-level references or cv-qualification (see section
|
||||||
references or cv-qualification (see section 5.2.8 in the C++
|
5.2.8 in the C++ standard). Unlike <code>std::type_info</code>,
|
||||||
standard). Unlike <code>std::type_info</code>,
|
|
||||||
<code>boost::python::type_info</code> instances are copyable, and
|
<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
|
<h4><a name="type_info-spec-synopsis"></a>Class type_info synopsis</h4>
|
||||||
synopsis</h4>
|
|
||||||
<pre>
|
<pre>
|
||||||
namespace boost { namespace python
|
namespace boost { namespace python
|
||||||
{
|
{
|
||||||
@@ -117,41 +118,41 @@ type_info(std::type_info const& = typeid(void));
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<dl class="function-semantics">
|
||||||
<dt><b>Effects:</b> constructs a <code>type_info</code> object
|
<dt><b>Effects:</b> constructs a <code>type_info</code> object which
|
||||||
which identifies the same type as its argument.
|
identifies the same type as its argument.</dt>
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Since it is occasionally neccessary to make
|
<dt><b>Rationale:</b> Since it is occasionally neccessary to make an
|
||||||
an array of <code>type_info</code> objects a benign default
|
array of <code>type_info</code> objects a benign default argument is
|
||||||
argument is supplied. <span class="c3"><b>Note:</b></span> this
|
supplied. <span class="c3"><b>Note:</b></span> this constructor does
|
||||||
constructor does <i>not</i> correct for non-conformance of
|
<i>not</i> correct for non-conformance of compiler
|
||||||
compiler <code>typeid()</code> implementations. See <code><a
|
<code>typeid()</code> implementations. See <code><a href=
|
||||||
href="#type_id-spec">type_id</a></code>, below.
|
"#type_id-spec">type_id</a></code>, below.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h4><a name="type_infospec-comparisons">Class
|
<h4><a name="type_infospec-comparisons">Class <code>type_info</code>
|
||||||
<code>type_info</code> comparisons</a></h4>
|
comparisons</a></h4>
|
||||||
<pre>
|
<pre>
|
||||||
bool operator<(type_info const& rhs) const;
|
bool operator<(type_info const& rhs) const;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<dl class="function-semantics">
|
||||||
<dt><b>Effects:</b> yields a total order over
|
<dt><b>Effects:</b> yields a total order over <code>type_info</code>
|
||||||
<code>type_info</code> objects.
|
objects.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
<pre>
|
<pre>
|
||||||
bool operator==(type_info const& rhs) const;
|
bool operator==(type_info const& rhs) const;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<dl class="function-semantics">
|
||||||
<dt><b>Returns:</b> <code>true</code> iff the two values describe
|
<dt><b>Returns:</b> <code>true</code> iff the two values describe the
|
||||||
the same type.
|
same type.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<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>
|
"../../../utility/operators.htm#totally_ordered1">totally_ordered</a><type_info></code>
|
||||||
as a private base class supplies operators <code><=</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>
|
</dl>
|
||||||
|
|
||||||
<h4><a name="type_infospec-observers">Class <code>type_info</code>
|
<h4><a name="type_infospec-observers">Class <code>type_info</code>
|
||||||
@@ -161,8 +162,8 @@ char const* name() const;
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<dl class="function-semantics">
|
||||||
<dt><b>Returns:</b> The result of calling <code>name()</code> on
|
<dt><b>Returns:</b> The result of calling <code>name()</code> on the
|
||||||
the argument used to construct the object.
|
argument used to construct the object.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2><a name="functions"></a>Functions</h2>
|
<h2><a name="functions"></a>Functions</h2>
|
||||||
@@ -171,25 +172,25 @@ std::ostream& operator<<(std::ostream&s, type_info const&x);
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<dl class="function-semantics">
|
||||||
<dt><b>Effects:</b> Writes a description of the type described by
|
<dt><b>Effects:</b> Writes a description of the type described by to
|
||||||
to <code>x</code> into <code>s</code>.
|
<code>x</code> into <code>s</code>.</dt>
|
||||||
|
|
||||||
<dt><b>Rationale:</b> Not every C++ implementation provides a
|
<dt><b>Rationale:</b> Not every C++ implementation provides a truly
|
||||||
truly human-readable <code>type_info::name()</code> string, but
|
human-readable <code>type_info::name()</code> string, but for some we
|
||||||
for some we may be able to decode the string and produce a
|
may be able to decode the string and produce a reasonable
|
||||||
reasonable representation.
|
representation.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
<pre>
|
<pre>
|
||||||
<a name="type_id-spec">template <class T> type_info type_id</a>()
|
<a name="type_id-spec">template <class T> type_info type_id</a>()
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<dl class="function-semantics">
|
<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
|
<dt><b>Note:</b> On some non-conforming C++ implementations, the code
|
||||||
code is not actually as simple as described above; the semantics
|
is not actually as simple as described above; the semantics are
|
||||||
are adjusted to work <i>as-if</i> the C++ implementation were
|
adjusted to work <i>as-if</i> the C++ implementation were
|
||||||
conforming.
|
conforming.</dt>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2><a name="examples"></a>Example</h2>
|
<h2><a name="examples"></a>Example</h2>
|
||||||
@@ -211,9 +212,11 @@ bool is_int(T x)
|
|||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||||
13 November, 2002
|
13 November, 2002
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="c4">© Copyright <a href=
|
<p class="c4">© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</p>
|
||||||
Rights Reserved.
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ struct return_internal_reference
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
Abrahams</a> 2002. </i>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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
|
// Hello World Example from the tutorial
|
||||||
// [Joel de Guzman 10/9/2002]
|
// [Joel de Guzman 10/9/2002]
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ GCCXML</a> to
|
|||||||
parse all the headers and extract the necessary information to automatically
|
parse all the headers and extract the necessary information to automatically
|
||||||
generate C++ code.</p>
|
generate C++ code.</p>
|
||||||
<a name="example"></a><h2>Example</h2><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>
|
tutorial</a>: </p>
|
||||||
<code><pre>
|
<code><pre>
|
||||||
<span class=keyword>struct </span><span class=identifier>World
|
<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
|
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
|
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
|
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>
|
tutorial</a>.</p>
|
||||||
<p>
|
<p>
|
||||||
The policies in Pyste are named exactly as in <a href="../../index.html">
|
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>
|
<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
|
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
|
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>
|
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>
|
<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">
|
Don't worry: normally <a href="http://www.gccxml.org">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||||
<title>Pyste Documentation</title>
|
<title>Pyste Documentation</title>
|
||||||
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<table width="100%" height="48" border="0" cellspacing="2">
|
<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