2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

..

24 Commits

Author SHA1 Message Date
nobody
43fb8c5a0f This commit was manufactured by cvs2svn to create tag
'Version_1_32_0'.

[SVN r26264]
2004-11-19 19:19:18 +00:00
Aleksey Gurtovoy
1a221e80b2 fix invalid (quickbook generated) links
[SVN r26263]
2004-11-19 19:19:17 +00:00
Aleksey Gurtovoy
41deb6855c correct //wrapper link
[SVN r26261]
2004-11-19 16:12:36 +00:00
Dave Abrahams
72207ba070 merged from trunk
[SVN r26259]
2004-11-19 15:51:02 +00:00
Dave Abrahams
f20ff9f9d6 merged from trunk
[SVN r26256]
2004-11-19 14:17:59 +00:00
Aleksey Gurtovoy
1afc3580a3 new MPL docs
[SVN r26213]
2004-11-15 12:30:30 +00:00
Joel de Guzman
ee1328e10d New Wrapper Facility
[SVN r26209]
2004-11-15 06:55:48 +00:00
Joel de Guzman
9ccde24cff New Wrapper Facility
[SVN r26208]
2004-11-15 06:43:54 +00:00
Joel de Guzman
168c8c692a New Wrapper Facility
[SVN r26207]
2004-11-15 06:34:34 +00:00
Dave Abrahams
3540d4fcf4 merged from trunk
[SVN r26090]
2004-11-02 20:11:53 +00:00
Dave Abrahams
0ccded7df3 merged from trunk
[SVN r26068]
2004-11-01 21:24:48 +00:00
nobody
f81c779823 This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r26058]
2004-11-01 16:41:45 +00:00
Dave Abrahams
8e4c69ee5a merged from trunk
[SVN r26050]
2004-11-01 14:17:40 +00:00
Dave Abrahams
3af8dc41d7 merged from trunk
[SVN r26048]
2004-11-01 14:15:48 +00:00
Dave Abrahams
1286cb0527 merged from trunk
[SVN r26027]
2004-11-01 00:23:09 +00:00
Aleksey Gurtovoy
baf3c962f3 fix broken links
[SVN r25987]
2004-10-31 02:50:40 +00:00
Joel de Guzman
6c7c9fb61f Fixed broken links
[SVN r25986]
2004-10-31 01:48:48 +00:00
Aleksey Gurtovoy
8aeaed2e5f fix libraries.html and other broken links
[SVN r25983]
2004-10-30 14:30:51 +00:00
Joel de Guzman
44b1c14d7e Fixed links
[SVN r25977]
2004-10-30 10:39:28 +00:00
Aleksey Gurtovoy
d65734aac4 merged const_argument fixes from the main trunk
[SVN r25925]
2004-10-29 03:21:18 +00:00
John Maddock
c99bd3ab00 Merged added copyrights from main branch.
[SVN r25913]
2004-10-28 11:06:12 +00:00
John Maddock
259a258123 BSL updates based on permissions in blanket-permission.txt
[SVN r25862]
2004-10-25 11:51:16 +00:00
Aleksey Gurtovoy
858055cd0a merge fixes from the main trunk
[SVN r25849]
2004-10-24 07:32:42 +00:00
nobody
197bb21fb7 This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r25797]
2004-10-20 08:26:43 +00:00
117 changed files with 5429 additions and 3108 deletions

View File

@@ -63,7 +63,6 @@ if [ check-python-config ]
$(bpl-linkflags)
<msvc-stlport><release>$(msvc-stlport-workarounds)
<darwin><*><linkflags>-bind_at_load
<gcc-3_3-darwin><*><linkflags>-bind_at_load
;
template extension

View File

@@ -1,39 +1,67 @@
import os ;
import modules ;
import python ;
# Use a very crude way to sense there python is locatted
if [ python.configured ] {
local PYTHON_PATH = [ modules.peek : PYTHON_PATH ] ;
if [ GLOB /usr/local/include/python2.2 : * ]
{
PYTHON_PATH = /usr/local ;
}
else if [ GLOB /usr/include/python2.2 : * ]
{
PYTHON_PATH = /usr ;
}
if [ os.name ] in CYGWIN NT
{
lib_condition = <link>shared: ;
defines = USE_DL_IMPORT ;
# Declare a target for the python interpreter library
lib python : : <name>python22 <search>$(PYTHON_PATH)/libs ;
PYTHON_LIB = python ;
}
else
{
lib python : : <name>python2.2 ;
PYTHON_LIB = python ;
}
if $(PYTHON_PATH) {
project boost/python
: source-location ../src
: requirements
#<include>$(PYTHON_PATH)/include
# $(lib_condition)<library-path>$(PYTHON_PATH)/libs
# <link>shared:<library>$(PYTHON_LIB)
# <define>$(defines)
#: usage-requirements # requirement that will be propageted to *users* of this library
# <include>$(PYTHON_PATH)/include
: requirements <include>$(PYTHON_PATH)/include
$(lib_condition)<library-path>$(PYTHON_PATH)/libs
<link>shared:<library>$(PYTHON_LIB)
<define>$(defines)
: usage-requirements # requirement that will be propageted to *users* of this library
<include>$(PYTHON_PATH)/include
# We have a bug which causes us to conclude that conditionalized
# properties in this section are not free.
# $(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
# <shared>true:<find-library>$(PYTHON_LIB)
# <library-path>$(PYTHON_PATH)/lib/python2.2/config
# <library>$(PYTHON_LIB)
<library-path>$(PYTHON_PATH)/lib/python2.2/config
<library>$(PYTHON_LIB)
;
lib boost_python
:
numeric.cpp
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
aix_init_module.cpp
converter/from_python.cpp
@@ -52,15 +80,8 @@ lib boost_python
object/iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
: <link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
<library>/python//python
: <link>shared
;
}
else
{
ECHO "warning: Python location is not configured" ;
ECHO "warning: the Boost.Python library won't be built" ;
;
}

View File

@@ -175,10 +175,6 @@ SOURCE=..\..\src\converter\registry.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\slice.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\str.cpp
# End Source File
# Begin Source File
@@ -189,10 +185,6 @@ SOURCE=..\..\src\tuple.cpp
SOURCE=..\..\src\converter\type_id.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\wrapper.cpp
# End Source File
# End Group
# Begin Group "Header Files"

View File

@@ -273,7 +273,7 @@ correctly:
==================
This section outlines some of the library's major features. Except as
necessary to avoid confusion, details of library implementation are
neccessary to avoid confusion, details of library implementation are
omitted.
-------------------------------------------
@@ -537,7 +537,7 @@ This has two effects:
called with an object wrapping a ``Derived`` instance. Wrapped
member functions of class ``T`` are treated as though they have an
implicit first argument of ``T&``, so these conversions are
necessary to allow the base class methods to be called for derived
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++
@@ -650,7 +650,7 @@ Things to notice about the dispatcher class:
called on an object of type ``BaseWrap``, since it overrides ``f``.
Admittedly, this formula is tedious to repeat, especially on a project
with many polymorphic classes; that it is necessary reflects
with many polymorphic classes; that it is neccessary reflects
limitations in C++'s compile-time reflection capabilities. Several
efforts are underway to write front-ends for Boost.Python which can
generate these dispatchers (and other wrapping code) automatically.

View File

@@ -82,12 +82,9 @@
boost installation (if you have already built boost from the top level
this may have no effect, since the work is already done).</p>
<h3><a name="configuration">Basic Configuration</a></h3> You may
need to configure the following variables to point Boost.Build at
your Python installation. Variables can be either set in the
environment or passed on the <code>bjam</code> command-line
as <code>-s</code><i>name</i><code>=</code><i>value</i>. Variable
names are case-sensitive.
<h3><a name="configuration">Basic Configuration</a></h3>
You may need to configure the following variables to point Boost.Build at
your Python installation:
<table border="1" summary="build configuration variables">
<tr>
@@ -101,29 +98,28 @@
</tr>
<tr>
<td><code>PYTHON_ROOT</code></td>
<td>The root directory of your Python installation</td>
<td>Windows:&nbsp;<code>c:/tools/python</code>
Unix:&nbsp;<code>/usr/local</code></td>
<td>On Unix, this is the <code>--with-prefix=</code> directory used
to configure Python</td>
</tr>
<tr>
<td><code>PYTHON_VERSION</code></td>
<td>The The 2-part python Major.Minor version number</td>
<td><code>2.4</code></td>
<td><code>2.2</code></td>
<td>Be sure not to include a third number, e.g. <b>not</b>
"<code>2.2.1</code>", even if that's the version you have.</td>
</tr>
<td><code>PYTHON_ROOT</code></td>
<td>The root directory of your Python installation</td>
<td>Windows:&nbsp;<code>c:/Python</code><i>(10*Version)</i>, e.g. <code>c:/Python24</code>
<br>
*nix/Cygwin:&nbsp;<code>/usr</code></td>
<td>On *nix, this should be the <code>--prefix=</code> directory used
to configure Python when it was built and installed.</td>
</tr>
<tr>
<td><code>PYTHON_INCLUDES</code></td>
@@ -176,7 +172,7 @@
<tr>
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
<td>*nix-style path containing the <code>include/</code> directory
<td>unix-style path containing the <code>include/</code> directory
containing
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
@@ -223,10 +219,8 @@
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
Users</a></h3>
<p>If you are using a version of Python prior to 2.4.1 with a
MinGW prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will
need to create a MinGW-compatible version of the Python library;
the one shipped with Python will only work with a
<p>You will need to create a MinGW-compatible version of the Python
library; the one shipped with Python will only work with a
Microsoft-compatible linker. Follow the instructions in the
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
chapter in <a href=
@@ -365,7 +359,7 @@ path-global BOOST_ROOT : ../../.. ;
<p>The first two variants of the <code>boost_python</code> library are
built by default, and are compatible with the default Python
distribution. The <code>debug-python</code> variant corresponds to a
specially-built debugging version of Python. On *nix platforms, this
specially-built debugging version of Python. On Unix platforms, this
python is built by adding <code>--with-pydebug</code> when configuring
the Python build. On Windows, the debugging version of Python is
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
@@ -443,7 +437,7 @@ path-global BOOST_ROOT : ../../.. ;
<blockquote>
<em>The Visual Studio project files are graciously contributed and
maintained by <a href="mailto:brett.calcott@gmail.com">Brett
maintained by <a href="mailto:brett.calcott@paradise.net.nz">Brett
Calcott</a></em>.
</blockquote>
<hr>

View File

@@ -5,7 +5,7 @@
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python</title>
</head>
@@ -24,60 +24,10 @@
<h2 align="center">Index</h2>
</td>
<td align="right">
<form method="get" action="http://www.google.com/custom">
<p>
<span id= "search-choice">
Search
<select name="hq" id="hq">
<option label="All Documentation" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc">
All Documentation
</option>
<option label="Tutorial" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc/tutorial">
Tutorial
</option>
<option label="Reference" value=
"site:www.boost.org inurl:www.boost.org/libs/python/doc/v2">
Reference
</option>
</select>
<br>
</span>
<span id="search-text">
<input type="text" name="q" id="q" size="31" maxlength="255" alt="Search Text" />
</span>
<br>
<span id= "google">
<a href= "http://www.google.com/search">
<img src="../../../more/google_logo_25wht.gif" alt="Google" border="0" /></a>Powered
</span>
<span id="go">
<input type="image" name="search" src="../../../more/space.gif" alt="Search" id="search-button" />
</span>
<br>
<input type="hidden" name="cof" value= "LW:277;L:http://www.boost.org/boost.png;LH:86;AH:center;GL:0;S:http://www.boost.org;AWFID:9b83d16ce652ed5a;" />
<input type="hidden" name="sa" value= "Google Search" />
<input type="hidden" name= "domains" value= "www.boost.org;mail.python.org" /></p>
</form>
</td>
</tr>
<tr>
</tr>
</table>
<hr>
<h2>Synopsis</h2>
Welcome to version 2 of <b>Boost.Python</b>, a C++ library which enables
seamless interoperability between C++ and the <a href=

328
doc/new-conversions.html Normal file
View File

@@ -0,0 +1,328 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>A New Type Conversion Mechanism for Boost.Python</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p><img border="0" src="../../../boost.png" width="277" height="86"
alt="boost logo"></p>
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
<h2>Introduction</h2>
This document describes a redesign of the mechanism for automatically
converting objects between C++ and Python. The current implementation
uses two functions for any type <tt>T</tt>:
<blockquote><pre>
U from_python(PyObject*, type&lt;T&gt;);
void to_python(V);
</pre></blockquote>
where U is convertible to T and T is convertible to V. These functions
are at the heart of C++/Python interoperability in Boost.Python, so
why would we want to change them? There are many reasons:
<h3>Bugs</h3>
<p>Firstly, the current mechanism relies on a common C++ compiler
bug. This is not just embarrassing: as compilers get to be more
conformant, the library stops working. The issue, in detail, is the
use of inline friend functions in templates to generate
conversions. It is a very powerful, and legal technique as long as
it's used correctly:
<blockquote><pre>
template &lt;class Derived&gt;
struct add_some_functions
{
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&amp;-opt</i>, ...);
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&amp;-opt</i>, ...);
};
template &lt;class T&gt;
struct some_template : add_some_functions&lt;some_template&lt;T&gt; &gt;
{
};
</pre></blockquote>
The <tt>add_some_functions</tt> template generates free functions
which operate on <tt>Derived</tt>, or on related types. Strictly
speaking the related types are not just cv-qualified <tt>Derived</tt>
values, pointers and/or references. Section 3.4.2 in the standard
describes exactly which types you must use as parameters to these
functions if you want the functions to be found
(there is also a less-technical description in section 11.5.1 of
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
with the current design, the <tt>from_python</tt> and
<tt>to_python</tt> functions are not supposed to be callable under any
conditions!
<h3>Compilation and Linking Time</h3>
The conversion functions generated for each wrapped class using the
above technique are not function templates, but regular functions. The
upshot is that they must <i>all</i> be generated regardless of whether
they are actually used. Generating all of those functions can slow
down module compilation, and resolving the references can slow down
linking.
<h3>Efficiency</h3>
The conversion functions are primarily used in (member) function
wrappers to convert the arguments and return values. Being functions,
converters have no interface which allows us to ask &quot;will the
conversion succeed?&quot; without calling the function. Since the
return value of the function must be the object to be passed as an
argument, Boost.Python currently uses C++ exception-handling to detect
an unsuccessful conversion. It's not a particularly good use of
exception-handling, since the failure is not handled very far from
where it occurred. More importantly, it means that C++ exceptions are
thrown during overload resolution as we seek an overload that matches
the arguments passed. Depending on the implementation, this approach
can result in significant slowdowns.
<p>It is also unclear that the current library generates a minimal
amount of code for any type conversion. Many of the conversion
functions are nontrivial, and partly because of compiler limitations,
they are declared <tt>inline</tt>. Also, we could have done a better
job separating the type-specific conversion code from the code which
is type-independent.
<h3>Cross-module Support</h3>
The current strategy requires every module to contain the definition
of conversions it uses. In general, a new module can never supply
conversion code which is used by another module. Ralf Grosse-Kunstleve
designed a clever system which imports conversions directly from one
library into another using some explicit declarations, but it has some
disadvantages also:
<ol>
<li>The system Ullrich Koethe designed for implicit conversion between
wrapped classes related through inheritance does not currently work if
the classes are defined in separate modules.
<li>The writer of the importing module is required to know the name of
the module supplying the imported conversions.
<li>There can be only one way to extract any given C++ type from a
Python object in a given module.
</ol>
The first item might be addressed by moving Boost.Python into a shared
library, but the other two cannot. Ralf turned the limitation in item
two into a feature: the required module is loaded implicitly when a
conversion it defines is invoked. We will probably want to provide
that functionality anyway, but it's not clear that we should require
the declaration of all such conversions. The final item is a more
serious limitation. If, for example, new numeric types are defined in
separate modules, and these types can all be converted to
<tt>double</tt>s, we have to choose just one conversion method.
<h3>Ease-of-use</h3>
One persistent source of confusion for users of Boost.Python has been
the fact that conversions for a class are not be visible at
compile-time until the declaration of that class has been seen. When
the user tries to expose a (member) function operating on or returning
an instance of the class in question, compilation fails...even though
the user goes on to expose the class in the same translation unit!
<p>
The new system lifts all compile-time checks for the existence of
particular type conversions and replaces them with runtime checks, in
true Pythonic style. While this might seem cavalier, the compile-time
checks are actually not much use in the current system if many classes
are wrapped in separate modules, since the checks are based only on
the user's declaration that the conversions exist.
<h2>The New Design</h2>
<h3>Motivation</h3>
The new design was heavily influenced by a desire to generate as
little code as possible in extension modules. Some of Boost.Python's
clients are enormous projects where link time is proportional to the
amount of object code, and there are many Python extension modules. As
such, we try to keep type-specific conversion code out of modules
other than the one the converters are defined in, and rely as much as
possible on centralized control through a shared library.
<h3>The Basics</h3>
The library contains a <tt>registry</tt> which maps runtime type
identifiers (actually an extension of <tt>std::type_info</tt> which
preserves references and constness) to entries containing type
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
(<tt>wrapper</tt>), but many converters from Python to C++
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
multiple modules try to register wrappers for the same type?</font>. Wrappers
and unwrappers are known as <tt>body</tt> objects, and are accessed
by the user and the library (in its function-wrapping code) through
corresponding <tt>handle</tt> (<tt>wrap&lt;T&gt;</tt> and
<tt>unwrap&lt;T&gt;</tt>) objects. The <tt>handle</tt> objects are
extremely lightweight, and delegate <i>all</i> of their operations to
the corresponding <tt>body</tt>.
<p>
When a <tt>handle</tt> object is constructed, it accesses the
registry to find a corresponding <tt>body</tt> that can convert the
handle's constructor argument. Actually the registry record for any
type
<tt>T</tt>used in a module is looked up only once and stored in a
static <tt>registration&lt;T&gt;</tt> object for efficiency. For
example, if the handle is an <tt>unwrap&lt;Foo&amp;&gt;</tt> object,
the <tt>entry</tt> for <tt>Foo&amp;</tt> is looked up in the
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
to determine if it can convert the
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
a body object which can perform the conversion is found, a pointer to
it is stored in the handle. A body object may at any point store
additional data in the handle to speed up the conversion process.
<p>
Now that the handle has been constructed, the user can ask it whether
the conversion can be performed. All handles can be tested as though
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
indicates success. If the user forges ahead and tries to do the
conversion without checking when no conversion is possible, an
exception will be thrown as usual. The conversion itself is performed
by the body object.
<h3>Handling complex conversions</h3>
<p>Some conversions may require a dynamic allocation. For example,
when a Python tuple is converted to a <tt>std::vector&lt;double&gt;
const&amp;</tt>, we need some storage into which to construct the
vector so that a reference to it can be formed. Furthermore, multiple
conversions of the same type may need to be &quot;active&quot;
simultaneously, so we can't keep a single copy of the storage
anywhere. We could keep the storage in the <tt>body</tt> object, and
have the body clone itself in case the storage is used, but in that
case the storage in the body which lives in the registry is never
used. If the storage was actually an object of the target type (the
safest way in C++), we'd have to find a way to construct one for the
body in the registry, since it may not have a default constructor.
<p>
The most obvious way out of this quagmire is to allocate the object using a
<i>new-expression</i>, and store a pointer to it in the handle. Since
the <tt>body</tt> object knows everything about the data it needs to
allocate (if any), it is also given responsibility for destroying that
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
object to tear down any data it may have stored there. In many ways,
you can think of the <tt>body</tt> as a &quot;dynamically-determined
vtable&quot; for the handle.
<h3>Eliminating Redundancy</h3>
If you look at the current Boost.Python code, you'll see that there
are an enormous number of conversion functions generated for each
wrapped class. For a given class <tt>T</tt>, functions are generated
to extract the following types <tt>from_python</tt>:
<blockquote><pre>
T*
T const*
T const* const&amp;
T* const&amp;
T&amp;
T const&amp;
T
std::auto_ptr&lt;T&gt;&amp;
std::auto_ptr&lt;T&gt;
std::auto_ptr&lt;T&gt; const&amp;
boost::shared_ptr&lt;T&gt;&amp;
boost::shared_ptr&lt;T&gt;
boost::shared_ptr&lt;T&gt; const&amp;
</pre></blockquote>
Most of these are implemented in terms of just a few conversions, and
<t>if you're lucky</t>, they will be inlined and cause no extra
overhead. In the new system, however, a significant amount of data
will be associated with each type that needs to be converted. We
certainly don't want to register a separate unwrapper object for all
of the above types.
<p>Fortunately, much of the redundancy can be eliminated. For example,
if we generate an unwrapper for <tt>T&</tt>, we don't need an
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
request to wrap/unwrap a given type is translated at compile-time into
a request which helps to eliminate redundancy. The rules used to
<tt>unwrap</tt> a type are:
<ol>
<li> Treat built-in types specially: when unwrapping a value or
constant reference to one of these, use a value for the target
type. It will bind to a const reference if neccessary, and more
importantly, avoids having to dynamically allocate room for
an lvalue of types which can be cheaply copied.
<li>
Reduce everything else to a reference to an un-cv-qualified type
where possible. Since cv-qualification is lost on Python
anyway, there's no point in trying to convert to a
<tt>const&amp;</tt>. <font color="#ff0000">What about conversions
to values like the tuple-&gt;vector example above? It seems to me
that we don't want to make a <tt>vector&lt;double&gt;&amp;</tt>
(non-const) converter available for that case. We may need to
rethink this slightly.</font>
</ol>
<p>To handle the problem described above in item 2, we modify the
procedure slightly. To unwrap any non-scalar <tt>T</tt>, we seek an
unwrapper for <tt>add_reference&lt;T&gt;::type</tt>. Unwrappers for
<tt>T&nbsp;const&amp;</tt> always return <tt>T&amp;</tt>, and are
registered under both <tt>T&nbsp;&amp;</tt> and
<tt>T&nbsp;const&amp;</tt>.
<p>For compilers not supporting partial specialization, unwrappers for
<tt>T&nbsp;const&amp;</tt> must return <tt>T&nbsp;const&amp;</tt>
(since constness can't be stripped), but a separate unwrapper object
need to be registered for <tt>T&nbsp;&amp;</tt> and
<tt>T&nbsp;const&amp;</tt> anyway, for the same reasons.
<font color="#ff0000">We may want to make it possible to compile as
though partial specialization were unavailable even on compilers where
it is available, in case modules could be compiled by different
compilers with compatible ABIs (e.g. Intel C++ and MSVC6).</font>
<h3>Efficient Argument Conversion</h3>
Since type conversions are primarily used in function wrappers, an
optimization is provided for the case where a group of conversions are
used together. Each <tt>handle</tt> class has a corresponding
&quot;<tt>_more</tt>&quot; class which does the same job, but has a
trivial destructor. Instead of asking each &quot;<tt>_more</tt>&quot;
handle to destroy its own body, it is linked into an endogenous list
managed by the first (ordinary) handle. The <tt>wrap</tt> and
<tt>unwrap</tt> destructors are responsible for traversing that list
and asking each <tt>body</tt> class to tear down its
<tt>handle</tt>. This mechanism is also used to determine if all of
the argument/return-value conversions can succeed with a single
function call in the function wrapping code. <font color="#ff0000">We
might need to handle return values in a separate step for Python
callbacks, since the availablility of a conversion won't be known
until the result object is retrieved.</font>
<br>
<hr>
<h2>References</h2>
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
<p>© Copyright David Abrahams, 2001</p>
</body>
</html>

111
doc/new-conversions.txt Normal file
View File

@@ -0,0 +1,111 @@
This hierarchy contains converter handle classes.
+-------------+
| noncopyable |
+-------------+
^
| A common base class used so that
+--------+--------+ conversions can be linked into a
| conversion_base | chain for efficient argument
+-----------------+ conversion
^
|
+---------+-----------+
| |
+-----------+----+ +------+-------+ only used for
| unwrap_more<T> | | wrap_more<T> | chaining, and don't manage any
+----------------+ +--------------+ resources.
^ ^
| |
+-----+-----+ +-------+-+ These converters are what users
| unwrap<T> | | wrap<T> | actually touch, but they do so
+-----------+ +---------+ through a type generator which
minimizes the number of converters
that must be generated, so they
Each unwrap<T>, unwrap_more<T>, wrap<T>, wrap_more<T> converter holds
a reference to an appropriate converter object
This hierarchy contains converter body classes
Exposes use/release which
are needed in case the converter
+-----------+ in the registry needs to be
| converter | cloned. That occurs when a
+-----------+ unwrap target type is not
^ contained within the Python object.
|
+------------------+-----+
| |
+--------+-------+ Exposes |
| unwrapper_base | convertible() |
+----------------+ |
^ |
| |
+--------+----+ +-----+-----+
| unwrapper<T>| | wrapper<T>|
+-------------+ +-----------+
Exposes T convert(PyObject*) Exposes PyObject* convert(T)
unwrap:
constructed with a PyObject*, whose reference count is
incremented.
find the registry entry for the target type
look in the collection of converters for one which claims to be
able to convert the PyObject to the target type.
stick a pointer to the unwrapper in the unwrap object
when unwrap is queried for convertibility, it checks to see
if it has a pointer to an unwrapper.
on conversion, the unwrapper is asked to allocate an
implementation if the unwrap object isn't already holding
one. The unwrap object "takes ownership" of the unwrapper's
implementation. No memory allocation will actually take place
unless this is a value conversion.
on destruction, the unwrapper is asked to free any implementation
held by the unwrap object. No memory deallocation actually
takes place unless this is a value conversion
on destruction, the reference count on the held PyObject is
decremented.
We need to make sure that by default, you can't instantiate
callback<> for reference and pointer return types: although the
unwrappers may exist, they may convert by-value, which would cause
the referent to be destroyed upon return.
wrap:
find the registry entry for the source type
see if there is a converter. If found, stick a pointer to it in
the wrap object.
when queried for convertibility, it checks to see if it has a
pointer to a converter.
on conversion, a reference to the target PyObject is held by the
converter. Generally, the PyObject will have been created by the
converter, but in certain cases it may be a pre-existing object,
whose reference count will have been incremented.
when a wrap<T> x is used to return from a C++ function,
x.release() is returned so that x no longer holds a reference to
the PyObject when destroyed.
Otherwise, on destruction, any PyObject still held has its
reference-count decremented.
When a converter is created by the user, the appropriate element must
be added to the registry; when it is destroyed, it must be removed
from the registry.

View File

@@ -1,171 +1,98 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="boost.css">
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - News/Change Log</title>
</head>
<title>Boost.Python - News/Change Log</title>
</head>
<body link="#0000FF" vlink="#800080">
<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>
<body link="#0000ff" vlink="#800080">
<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>
<td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
<td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
<h2 align="center">News/Change Log</h2>
</td>
</tr>
</table>
<hr>
<h2 align="center">News/Change Log</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt>19 October 2005 - 1.33.1 release</dt>
<dl class="page-index">
<dt>19 November 2004 - 1.32 release</dt>
<dd>
<ul>
<li><code>wrapper&lt;T&gt;</code> can now be used as expected with a
held type of <i>some-smart-pointer</i><code>&lt;T&gt;</code></li>
<dd>
<ul>
<li>Updated to use the Boost Software License.</li>
<li>A new, <a href="tutorial/doc/html/python/exposing.html#python.class_virtual_functions">better method of wrapping classes with virtual functions</a> has been implemented.</li>
<li>Support for upcoming GCC symbol export control features have been folded in, thanks to Niall Douglas.</li>
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i> of function parameter types part of the function type has been worked around.</li>
<li>Components used by other libraries have been moved out of <code>python/detail</code> and into <code> boost/detail</code> to improve dependency relationships.</li>
<li>Miscellaneous bug fixes and compiler workarounds.</li>
</ul>
</dd>
<dt>8 Sept 2004</dt>
<li>The build now assumes Python 2.4 by default, rather than 2.2</li>
<dd>
Support for Python's Bool type, thanks to <a
mailto="dholth-at-fastmail.fm">Daniel Holth</a>.
</dd>
<li>Support Python that's built without Unicode support</li>
<dt>11 Sept 2003</dt>
<li>Support for wrapping classes with overloaded address-of
(<code>&amp;</code>) operators</li>
</ul>
</dd>
<dd>
<ul>
<li>Changed the response to multiple to-python converters being
registered for the same type from a hard error into warning;
Boost.Python now reports the offending type in the message.</li>
<dt>14 August 2005 - 1.33 release</dt>
<li>Added builtin <code>std::wstring</code> conversions</li>
<dd>
<ul>
<li>Support for docstrings on nonstatic properties.</li>
<li>Added <code>std::out_of_range</code> =&gt; Python
<code>IndexError</code> exception conversion, thanks to <a href=
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
</ul>
</dd>
<li>We now export the client-provided docstrings for
<code>init&lt;optional&lt;&gt; &gt;</code> and
<i>XXX</i><code>_FUNCTION_OVERLOADS()</code> for only the last
overload.</li>
<dt>9 Sept 2003</dt>
<li>Fixed some support for Embedded VC++ 4</li>
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
<li>Better support for rvalue from-python conversions of shared_ptr:
always return a pointer that holds the owning python object *unless*
the python object contains a NULL shared_ptr holder of the right
type.</li>
<dt>constructors which take a range of characters, allowing strings
containing nul (<code>'\0'</code>) characters.</dt>
<li>Support for exposing <code>vector&lt;T*&gt;</code> with the
indexing suite.</li>
<dt>8 Sept 2003</dt>
<li>Support for GCC-3.3 on MacOS.</li>
<dd>Added the ability to create methods from function objects (with an
<code>operator()</code>); see the <a href=
"v2/make_function.html#make_function-spec">make_function</a> docs for
more info.</dd>
<li>updated visual studio project build file to include two new files
(slice.cpp and wrapper.cpp)</li>
<dt>10 August 2003</dt>
<li>Added search feature to the index page.</li>
<dd>Added the new <code>properties</code> unit tests contributed by <a
href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and documented
<code>add_static_property</code> at his urging.</dd>
<li>Numerous fixes to the tutorial</li>
<dt>1 August 2003</dt>
<li>Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG
2.45</li>
</ul>
</dd>
<dt>11 March 2005</dt>
<dd>
<ul>
<li>Added a hack that will fool PyDoc into working with Boost.Python,
thanks to Nick Rasmussen</li>
</ul>
</dd>
<dt>19 November 2004 - 1.32 release</dt>
<dd>
<ul>
<li>Updated to use the Boost Software License.</li>
<li>A new, <a href=
"tutorial/doc/html/python/exposing.html#python.class_virtual_functions">
better method of wrapping classes with virtual functions</a> has been
implemented.</li>
<li>Support for upcoming GCC symbol export control features have been
folded in, thanks to Niall Douglas.</li>
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i>
of function parameter types part of the function type has been worked
around.</li>
<li>Components used by other libraries have been moved out of
<code>python/detail</code> and into <code>boost/detail</code> to
improve dependency relationships.</li>
<li>Miscellaneous bug fixes and compiler workarounds.</li>
</ul>
</dd>
<dt>8 Sept 2004</dt>
<dd>Support for Python's Bool type, thanks to <a href=
"mailto:dholth-at-fastmail.fm">Daniel Holth</a>.</dd>
<dt>11 Sept 2003</dt>
<dd>
<ul>
<li>Changed the response to multiple to-python converters being
registered for the same type from a hard error into warning;
Boost.Python now reports the offending type in the message.</li>
<li>Added builtin <code>std::wstring</code> conversions</li>
<li>Added <code>std::out_of_range</code> =&gt; Python
<code>IndexError</code> exception conversion, thanks to <a href=
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
</ul>
</dd>
<dt>9 Sept 2003</dt>
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
<dt>constructors which take a range of characters, allowing strings
containing nul (<code>'\0'</code>) characters.</dt>
<dt>8 Sept 2003</dt>
<dd>Added the ability to create methods from function objects (with an
<code>operator()</code>); see the <a href=
"v2/make_function.html#make_function-spec">make_function</a> docs for
more info.</dd>
<dt>10 August 2003</dt>
<dd>Added the new <code>properties</code> unit tests contributed by
<a href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and
documented <code>add_static_property</code> at his urging.</dd>
<dt>1 August 2003</dt>
<dd>
Added the new <code>arg</code> class contributed by <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
ability to wrap functions that can be called with ommitted arguments in
the middle:
<pre>
<dd>
Added the new <code>arg</code> class contributed by <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
ability to wrap functions that can be called with ommitted arguments
in the middle:
<pre>
void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
BOOST_PYTHON_MODULE(test)
@@ -174,104 +101,111 @@ BOOST_PYTHON_MODULE(test)
, (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
}
</pre>And in Python:
<pre>
</pre>
And in Python:
<pre>
&gt;&gt;&gt; import test
&gt;&gt;&gt; f(0, z = "bar")
&gt;&gt;&gt; f(z = "bar", y = 0.0)
</pre>Thanks, Nikolay!
</dd>
</pre>
Thanks, Nikolay!
</dd>
<dt>22 July 2003</dt>
<dt>22 July 2003</dt>
<dd>Killed the dreaded "bad argument type for builtin operation" error.
Argument errors now show the actual and expected argument types!</dd>
<dd>Killed the dreaded "bad argument type for builtin operation" error.
Argument errors now show the actual and expected argument types!</dd>
<dt>19 July 2003</dt>
<dt>19 July 2003</dt>
<dd>Added the new <code><a href=
"v2/return_arg.html">return_arg</a></code> policy from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
<dd>Added the new <code><a href=
"v2/return_arg.html">return_arg</a></code> policy from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks,
Nikolay!</dd>
<dt>18 March, 2003</dt>
<dt>18 March, 2003</dt>
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Gan&szlig;auge</a> has contributed <a href=
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
Oliveira</a> has contributed the exciting <a href=
"../pyste/index.html">Pyste</a> ("Pie-steh") package.</dd>
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Gan&szlig;auge</a> has contributed <a href=
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a>
has contributed the exciting <a href="../pyste/index.html">Pyste</a>
("Pie-steh") package.</dd>
<dt>24 February 2003</dt>
<dt>24 February 2003</dt>
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now any
wrapped object of C++ class <code>X</code> can be converted automatically
to <code>shared_ptr&lt;X&gt;</code>, regardless of how it was wrapped.
The <code>shared_ptr</code> will manage the lifetime of the Python object
which supplied the <code>X</code>, rather than just the <code>X</code>
object itself, and when such a <code>shared_ptr</code> is converted back
to Python, the original Python object will be returned.</dd>
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now
any wrapped object of C++ class <code>X</code> can be converted
automatically to <code>shared_ptr&lt;X&gt;</code>, regardless of how it
was wrapped. The <code>shared_ptr</code> will manage the lifetime of
the Python object which supplied the <code>X</code>, rather than just
the <code>X</code> object itself, and when such a
<code>shared_ptr</code> is converted back to Python, the original
Python object will be returned.</dd>
<dt>19 January 2003</dt>
<dt>19 January 2003</dt>
<dd>Integrated <code>staticmethod</code> support from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
<dd>Integrated <code>staticmethod</code> support from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks,
Nikolay!</dd>
<dt>29 December 2002</dt>
<dt>29 December 2002</dt>
<dd>Added Visual Studio project file and instructions from Brett Calcott.
Thanks, Brett!</dd>
<dd>Added Visual Studio project file and instructions from Brett
Calcott. Thanks, Brett!</dd>
<dt>20 December 2002</dt>
<dt>20 December 2002</dt>
<dd>Added automatic downcasting for pointers, references, and smart
pointers to polymorphic class types upon conversion to python</dd>
<dd>Added automatic downcasting for pointers, references, and smart
pointers to polymorphic class types upon conversion to python</dd>
<dt>18 December 2002</dt>
<dt>18 December 2002</dt>
<dd>Optimized from_python conversions for wrapped classes by putting the
conversion logic in the shared library instead of registering separate
converters for each class in each extension module</dd>
<dd>Optimized from_python conversions for wrapped classes by putting
the conversion logic in the shared library instead of registering
separate converters for each class in each extension module</dd>
<dt>19 November 2002</dt>
<dt>19 November 2002</dt>
<dd>Removed the need for users to cast base class member function
pointers when used as arguments to <a href=
"v2/class.html#class_-spec-modifiers">add_property</a></dd>
<dd>Removed the need for users to cast base class member function
pointers when used as arguments to <a href=
"v2/class.html#class_-spec-modifiers">add_property</a></dd>
<dt>13 December 2002</dt>
<dt>13 December 2002</dt>
<dd>Allow exporting of <a href=
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
Fixed unsigned integer conversions to deal correctly with numbers that
are out-of-range of <code>signed long</code>.</dd>
<dd>Allow exporting of <a href=
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
Fixed unsigned integer conversions to deal correctly with numbers that
are out-of-range of <code>signed long</code>.</dd>
<dt>14 November 2002</dt>
<dt>14 November 2002</dt>
<dd>Auto-detection of class data members wrapped with <a href=
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
<dd>Auto-detection of class data members wrapped with <a href=
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
<dt>13 November 2002</dt>
<dt>13 November 2002</dt>
<dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd>
<dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd>
<dt>October 2002</dt>
<dt>October 2002</dt>
<dd>Ongoing updates and improvements to tutorial documentation</dd>
<dd>Ongoing updates and improvements to tutorial documentation</dd>
<dt>10 October 2002</dt>
<dt>10 October 2002</dt>
<dd>Boost.Python V2 is released!</dd>
</dl>
<hr>
<dd>Boost.Python V2 is released!</dd>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
19 November 2004
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
19 November 2004
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p>
</body>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - Projects using Boost.Python</title>
@@ -42,7 +42,7 @@
<dl class="page-index">
<dt><b><a href=
"http://www.neuralynx.com">NeuraLab</a></b></dt>
"http://www.neuralynx.com/neuralab/index.htm">NeuraLab</a></b></dt>
<dd>Neuralab is a data analysis environment specifically tailored for
neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
@@ -141,34 +141,6 @@
<h3>Games</h3>
<dl>
<dt><b><a href="http://www.firaxis.com">Civilization IV</a></b></dt>
</dl>
<blockquote>
“The fourth game in the PC strategy series that has
sold over five million copies, Sid Meier's Civilization IV is a bold
step forward for the franchise, with spectacular new 3D graphics and
all-new single and multiplayer content. Civilization IV will also set a
new standard for user-modification, allowing gamers to create their own
add-ons using Python and XML.
<p>Sid Meier's Civilization IV will be released for PC in late 2005.
For more information please visit <a href=
"http://www.firaxis.com">http://www.firaxis.com</a> or write <a href=
"mailto:kgilmore@firaxis.com">kgilmore@firaxis.com</a></p>
</blockquote>
<p>Boost.Python is used as the interface layer between the C++ game code
and Python. Python is used for many purposes in the game, including map
generation, interface screens, game events, tools, tutorials, etc. Most
high-level game operations have been exposed to Python in order to give
modders the power they need to customize the game.</p>
<blockquote>
-Mustafa Thamer, Civ4 Lead Programmer
</blockquote>
<dl class="page-index">
<dt><b><a href="http://vegastrike.sourceforge.net">Vega
Strike</a></b></dt>
@@ -231,8 +203,8 @@
<dt><a href="http://www.iplt.org"><b>IPLT</b></a></dt>
<dd>
<a href="mailto:ansgar.philippsen-at-unibas.ch">Ansgar Philippsen</a>
writes:
<a href="mailto:ansgar.philippsen-at-unibas.ch">Ansgar
Philippsen</a> writes:
<blockquote>
IPLT is an image processing library and toolbox for the structural
@@ -351,13 +323,13 @@
<p>Two projects have been developed so far with this technology:</p>
<p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Simba</a></b>
<p><b><a href="http://www.esss.com.br/dev_simba.phtml">Simba</a></b>
provides 3D visualization of geological formations gattered from the
simulation of the evolution of oil systems, allowing the user to
analyse various aspects of the simulation, like deformation, pressure
and fluids, along the time of the simulation.</p>
<p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Aero</a></b>
<p><b><a href="http://www.esss.com.br/dev_aero.phtml">Aero</a></b>
aims to construct a CFD with brazilian technology, which involves
various companies and universities. ESSS is responsible for various
of the application modules, including GUI and post-processing of
@@ -388,24 +360,6 @@
</dd>
</dl>
<h3>Systems Libraries</h3>
<dl>
<dt><a href="http://itamarst.org/software"><b>Fusion</b></a></dt>
<dd>
<p>Fusion is a library that supports implementing protocols in C++
for use with Twisted, allowing control over memory allocation
strategies, fast method calls internally, etc.. Fusion supports TCP,
UDP and multicast, and is implemented using the Boost.Python python
bindings.</p>
<p>Fusion is licensed under the MIT license, and available for
download from <a href=
"http://itamarst.org/software">http://itamarst.org/software</a>.</p>
</dd>
</dl>
<h3>Tools</h3>
<dl>
@@ -430,7 +384,7 @@
15 July, 2003</p>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p>
Abrahams</a> 2002-2003. </i></p>
</body>
</html>

View File

@@ -1,12 +1,8 @@
project boost/libs/python/doc/tutorial/doc ;
import boostbook : boostbook ;
using quickbook ;
boostbook tutorial
:
tutorial.qbk
:
<xsl:param>boost.root=../../../../../..
<xsl:param>boost.libraries=../../../../../../libs/libraries.htm
boostbook tutorial : tutorial.xml
: <xsl:param>boost.root=../../../../../..
<xsl:param>boost.libraries=../../../../../libraries.htm
;

View File

@@ -0,0 +1,9 @@
index.html
python/hello.html
python/exposing.html
python/functions.html
python/object.html
python/embedding.html
python/iterators.html
python/exception.html
python/techniques.html

View File

@@ -1,5 +1,5 @@
/*=============================================================================
Copyright (c) 2004 Joel de Guzman
Copyright (c) 2002 2004 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
@@ -7,424 +7,289 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
/*=============================================================================
Body defaults
=============================================================================*/
/* CSS based on w3c documentation which I like a lot, and the classic Spirit
documentation. */
body
/* Body defaults */
body
{
padding: 2em 1em 2em 1em;
margin: 1em 1em 1em 1em;
font-family: sans-serif;
}
/* Paragraphs */
p
{
text-align: justify;
}
pre.synopsis
{
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Headings */
h1, h2, h3, h4, h5, h6 { text-align: left; margin-top: 2pc; }
h1 { font: 170% sans-serif }
h2 { font: bold 140% sans-serif }
h3 { font: 120% sans-serif }
h4 { font: bold 100% sans-serif }
h5 { font: italic 100% sans-serif }
h6 { font: italic 100% sans-serif }
/* Unordered lists */
ul
{
text-align: justify;
}
/* Links */
a
{
text-decoration: none; /* no underline */
}
a:hover
{
text-decoration: underline;
}
/* Top page title */
title, h1.title, h2.title, h3.title,
h4.title, h5.title, h6.title,
.refentrytitle
{
font-weight: bold;
font-size: 2pc;
margin-bottom: 1pc;
}
/* Spirit style navigation */
.spirit-nav
{
text-align: right;
}
.spirit-nav a
{
color: white;
padding-left: 0.5em;
}
.spirit-nav img
{
border-width: 0px;
}
/* Program listing box */
.programlisting, .screen
{
display: block;
margin-left: 4%;
margin-right: 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Table of contents */
.toc
{
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
.boost-toc
{
float: right;
padding: 0.5pc;
}
/* Tables */
.table-title, div.table p.title
{
margin-left: 4%;
padding-right: 0.5em;
padding-left: 0.5em;
font-size: 120%;
}
.informaltable table, .table table
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
div.informaltable table, div.table table
{
padding: 4px 4px 4px 4px;
}
div.informaltable table tr td, div.table table tr td
{
padding: 0.5em 0.5em 0.5em 0.5em;
text-align: justify;
}
div.informaltable table tr th, div.table table tr th
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
}
/* inlined images */
.inlinemediaobject
{
padding: 0.5em 0.5em 0.5em 0.5em;
}
/* tone down the title of Parameter lists */
div.variablelist p.title
{
font-weight: bold;
font-size: 100%;
text-align: left;
}
/* tabularize parameter lists */
div.variablelist dl dt
{
float: left;
clear: left;
display: block;
font-style: italic;
}
div.variablelist dl dd
{
display: block;
clear: right;
padding-left: 8pc;
}
/* title of books and articles in bibliographies */
span.title
{
font-style: italic;
}
@media screen
{
a
{
margin: 1em;
font-family: sans-serif;
color: #005a9c;
}
/*=============================================================================
Paragraphs
=============================================================================*/
p
a:visited
{
text-align: justify;
font-size: 11pt;
line-height: 1.2;
color: #9c5a9c;
}
/*=============================================================================
Program listings
=============================================================================*/
/* Syntax Highlighting */
.keyword { color: #0000AA; font-weight: bold; }
.identifier {}
.special { color: #707070; }
.preprocessor { color: #402080; font-weight: bold; }
.char { color: teal; }
.comment { color: #800000; }
.string { color: teal; }
.number { color: teal; }
.copyright { color: #666666; font-size: small; }
.white_bkd { background-color: #FFFFFF; }
.dk_grey_bkd { background-color: #999999; }
tt.computeroutput
pre.synopsis
{
font-size: 10pt;
background-color: #f3f3f3;
}
.programlisting, .screen
{
background-color: #f3f3f3;
}
/* Table of contents */
.toc
{
background-color: #f3f3f3;
}
div.informaltable table tr td, div.table table tr td
{
background-color: #F3F3F3;
border: 1pt solid white;
}
div.informaltable table tr th, div.table table tr th
{
background-color: #e4e4e4;
}
span.highlight
{
color: #00A000;
}
}
@media print
{
a
{
color: black;
}
a:visited
{
color: black;
}
.spirit-nav
{
display: none;
}
/* Syntax Highlighting */
.keyword
{
font-weight: bold;
}
pre.synopsis
{
font-size: 10pt;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
border: 1px solid gray;
}
.programlisting,
.screen
.programlisting, .screen
{
font-size: 10pt;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
border: 1px solid gray;
}
/*=============================================================================
Headings
=============================================================================*/
h1,
h2,
h3,
h4,
h5,
h6
{
text-align: left;
margin-top: 2pc;
}
h1 { font: 170% }
h2 { font: bold 140% }
h3 { font: bold 120% }
h4 { font: bold 100% }
h5 { font: italic 100% }
h6 { font: italic 100% }
/* Top page titles */
title,
h1.title,
h2.title
h3.title,
h4.title,
h5.title,
h6.title,
.refentrytitle
{
font-weight: bold;
margin-bottom: 1pc;
}
h1.title { font-size: 220% }
h2.title { font-size: 220% }
h3.title { font-size: 170% }
h4.title { font-size: 140% }
h5.title { font-size: 120% }
h6.title { font-size: 120% }
/*=============================================================================
Lists
=============================================================================*/
li
{
font-size: 11pt;
line-height: 1.3;
}
/* Unordered lists */
ul
{
text-align: justify;
}
/* Ordered lists */
ol
{
text-align: justify;
}
/*=============================================================================
Links
=============================================================================*/
a
{
text-decoration: none; /* no underline */
}
a:hover
{
text-decoration: underline;
}
/*=============================================================================
Spirit style navigation
=============================================================================*/
.spirit-nav
{
text-align: right;
}
.spirit-nav a
{
color: white;
padding-left: 0.5em;
}
.spirit-nav img
{
border-width: 0px;
}
/*=============================================================================
Table of contents
=============================================================================*/
/* Table of contents */
.toc
{
margin: 1pc 4% 0pc 4%;
padding: 0.5pc;
font-size: 11pt;
line-height: 1.3;
}
.boost-toc
{
float: right;
padding: 0.5pc;
border: 1px solid gray;
}
/*=============================================================================
Tables
=============================================================================*/
.table-title,
div.table p.title
.informaltable table, .table table
{
margin-left: 4%;
padding-right: 0.5em;
padding-left: 0.5em;
font-size: 120%;
}
.informaltable table,
.table table
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
div.informaltable table,
div.table table
{
padding: 4px;
}
/* Table Cells */
div.informaltable table tr td,
div.table table tr td
{
padding: 0.5em;
text-align: justify;
font-size: 11pt;
border: 1px solid gray;
border-collapse: collapse;
}
div.informaltable table tr th,
div.table table tr th
div.informaltable table tr td, div.table table tr td
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
border: 1px solid gray;
}
/*=============================================================================
Blurbs
=============================================================================*/
div.informaltable table tr td.blurb
div.informaltable table tr th, div.table table tr th
{
font-size: 10pt; /* A little bit smaller than the main text */
line-height: 1.2;
}
td.blurb img
{
padding: 1pt;
border: 1px solid gray;
}
/*=============================================================================
Misc
=============================================================================*/
/* Tone down the title of Parameter lists */
div.variablelist p.title
span.highlight
{
font-weight: bold;
font-size: 100%;
text-align: left;
}
/* Tabularize parameter lists */
div.variablelist dl dt
{
float: left;
clear: left;
display: block;
font-style: italic;
}
div.variablelist dl dd
{
display: block;
clear: right;
padding-left: 8pc;
}
/* Title of books and articles in bibliographies */
span.title
{
font-style: italic;
}
span.underline
{
text-decoration: underline;
}
span.strikethrough
{
text-decoration: line-through;
}
/* Copyright, Legal Notice */
div div.legalnotice p
{
text-align: left
}
/*=============================================================================
Colors
=============================================================================*/
@media screen
{
/* Links */
a
{
color: #005a9c;
}
a:visited
{
color: #9c5a9c;
}
/* Syntax Highlighting */
.keyword { color: #0000AA; }
.identifier { color: #000000; }
.special { color: #707070; }
.preprocessor { color: #402080; }
.char { color: teal; }
.comment { color: #800000; }
.string { color: teal; }
.number { color: teal; }
.white_bkd { background-color: #FFFFFF; }
.dk_grey_bkd { background-color: #999999; }
/* Copyright, Legal Notice */
.copyright
{
color: #666666;
font-size: small;
}
div div.legalnotice p
{
color: #666666;
}
/* Program listing */
pre.synopsis
{
background-color: #F3F3F3;
border: 1pt solid #C0C0C0;
}
.programlisting,
.screen
{
background-color: #F3F3F3;
border: 1pt solid #C0C0C0;
}
/* Blurbs */
div.informaltable table tr td.blurb
{
background-color: #FFFFF0;
border: 1pt solid #707070;
}
/* Table of contents */
.toc
{
background-color: #F3F3F3;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
background-color: #F0F0F0;
}
div.informaltable table tr th,
div.table table tr th
{
background-color: #E4E4E4;
}
/* Misc */
span.highlight
{
color: #00A000;
}
}
@media print
{
/* Links */
a
{
color: black;
}
a:visited
{
color: black;
}
.spirit-nav
{
display: none;
}
/* Program listing */
pre.synopsis
{
border: 1px solid gray;
}
.programlisting,
.screen
{
border: 1px solid gray;
}
/* Table of contents */
.toc
{
border: 1px solid gray;
}
.informaltable table,
.table table
{
border: 1px solid gray;
border-collapse: collapse;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid gray;
}
div.informaltable table tr th,
div.table table tr th
{
border: 1px solid gray;
}
/* Misc */
span.highlight
{
font-weight: bold;
}
}
}

View File

@@ -11,7 +11,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">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="../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
@@ -28,9 +28,9 @@
<div><div class="author"><h3 class="author">
<span class="firstname">David</span> <span class="surname">Abrahams</span>
</h3></div></div>
<div><p class="copyright">Copyright © 2002-2005 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">
<a name="id442427"></a><p>
<a name="id376569"></a><p>
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -96,7 +96,7 @@ metaprogramming techniques simplifies its syntax for users, so that
wrapping code takes on the look of a kind of declarative interface
definition language (IDL).</p>
<a name="quickstart.hello_world"></a><h2>
<a name="id372086"></a>Hello World</h2>
<a name="id376600"></a>Hello World</h2>
<p>
Following C/C++ tradition, let's start with the "hello, world". A C++
Function:</p>
@@ -116,16 +116,14 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
<p>
That's it. We're done. We can now build this as a shared library. The
resulting DLL is now visible to Python. Here's a sample Python session:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
hello</span><span class="special">,</span><span class="identifier"> world</span></tt></pre>
<p></p>
<div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module from start to finish...</b></span></em></span></p></blockquote></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><small><p>Last revised: July 12, 2005 at 07:50:43 GMT</p></small></td>
<td align="left"><small><p>Last revised: October 12, 2004 at 03:11:11 GMT</p></small></td>
<td align="right"><small></small></td>
</tr></table>
<hr>

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -39,7 +39,7 @@ the gaps. However, Boost.Python already makes embedding a lot easier and,
in a future version, it may become unnecessary to touch the Python/C API at
all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
<a name="embedding.building_embedded_programs"></a><h2>
<a name="id456196"></a>Building embedded programs</h2>
<a name="id460514"></a>Building embedded programs</h2>
<p>
To be able to use embedding in your programs, they have to be linked to
both Boost.Python's and Python's static link library.</p>
@@ -59,36 +59,39 @@ Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be
include path.</p>
<p>
In a Jamfile, all the above boils down to:</p>
<pre class="programlisting"><tt class="literal">projectroot c:\projects\embedded_program ; # location of the program
<pre class="programlisting"><tt class="literal"> projectroot c:\projects\embedded_program ; # location of the program
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
&lt;find-library&gt;boost_python &lt;library-path&gt;c:\boost\libs\python
$(PYTHON_PROPERTIES)
&lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
&lt;find-library&gt;boost_python &lt;library-path&gt;c:\boost\libs\python
$(PYTHON_PROPERTIES)
&lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
</tt></pre>
<a name="embedding.getting_started"></a><h2>
<a name="id456277"></a>Getting started</h2>
<a name="id460605"></a>Getting started</h2>
<p>
Being able to build is nice, but there is nothing to build yet. Embedding
the Python interpreter into one of your C++ programs requires these 4
steps:</p>
<div class="orderedlist"><ol type="1">
<li>
#include <tt class="literal">&lt;boost/python.hpp&gt;</tt><br><br>
#include <tt class="literal">&lt;boost/python.hpp&gt;</tt><p></p>
<p></p>
</li>
<li>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>() to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt> module.<br><br>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>() to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt> module.<p></p>
<p></p>
</li>
<li>
Call other Python C API routines to use the interpreter.<br><br>
Call other Python C API routines to use the interpreter.<p></p>
<p></p>
</li>
<li>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>() to stop the interpreter and release its resources.
@@ -110,7 +113,7 @@ 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
<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="id456409"></a>Reference-counting handles and objects</h2>
<a name="id460737"></a>Reference-counting handles and objects</h2>
<p>
There are two ways in which a function in the Python/C API can return a
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span> or as a <span class="emphasis"><em>new reference</em></span>. Which of
@@ -136,12 +139,14 @@ such function that returns a new reference is <a href="http://www.python.org/doc
discuss in the next section.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why haven't we been using any template parameters?</b></span><br><br><tt class="literal">handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt class="literal">PyObject</tt> 99% of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt> for convenience. Therefore we can use the shorthand <tt class="literal">handle&lt;&gt;</tt> instead of the longer, but equivalent, <tt class="literal">handle&lt;PyObject&gt;</tt>.
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why haven't we been using any template parameters?</b></span><p></p>
<p></p>
<tt class="literal">handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt class="literal">PyObject</tt> 99% of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt> for convenience. Therefore we can use the shorthand <tt class="literal">handle&lt;&gt;</tt> instead of the longer, but equivalent, <tt class="literal">handle&lt;PyObject&gt;</tt>.
</td></tr></tbody>
</table></div>
<a name="using_the_interpreter.running_python_code"></a><h2>
<a name="id456714"></a>Running Python code</h2>
<a name="id461039"></a>Running Python code</h2>
<p>
To run Python code from C++ there is a family of functions in the API
starting with the PyRun prefix. You can find the full list of these
@@ -156,7 +161,7 @@ The <tt class="literal">start</tt> parameter is the start symbol from the Python
for interpreting the code. The possible values are:</p>
<div class="informaltable">
<h4>
<a name="id456876"></a><span class="table-title">Start symbols</span>
<a name="id461201"></a><span class="table-title">Start symbols</span>
</h4>
<table class="table">
<colgroup>
@@ -214,17 +219,12 @@ the object's <tt class="literal">ptr</tt> member function to retrieve the <tt cl
<p>
This should create a file called 'hello.txt' in the current directory
containing a phrase that is well-known in programming circles.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> in a
(nameless) <tt class="literal">handle</tt> even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s.
</td></tr></tbody>
</table></div>
<p><span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> in a
(nameless) <tt class="literal">handle</tt> even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap <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="id457324"></a>Beyond handles</h2>
<a name="id461639"></a>Beyond handles</h2>
<p>
It's nice that <tt class="literal">handle</tt> manages the reference counting details for us, but
other than that it doesn't do much. Often we'd like to have a more useful
@@ -261,17 +261,12 @@ the dictionary. Another way to achieve the same result is to let
));</span><span class="keyword">
int</span><span class="identifier"> five_squared</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span></tt></pre>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member function to return the wrapped
<tt class="literal">PyObject*</tt> is called <tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense if you
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt>
perform.
</td></tr></tbody>
</table></div>
<p><span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member function to return the wrapped
<tt class="literal">PyObject*</tt> is called <tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense if you
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt>
perform.</p>
<a name="using_the_interpreter.exception_handling"></a><h2>
<a name="id457906"></a>Exception handling</h2>
<a name="id462209"></a>Exception handling</h2>
<p>
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
function returns a null pointer. Constructing a <tt class="literal">handle</tt> out of this null
@@ -301,7 +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
<a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a> to
print the exception's traceback to the console, or comparing the type of the
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard exceptions</a>:</p>
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html%20standard" target="_top">exceptions</a>:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span><span class="special">
{</span><span class="keyword">
if</span><span class="special"> (</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span><span class="special">
@@ -336,7 +331,7 @@ if</span><span class="special"> (!</span><span class="identifier">result</span><
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -44,7 +44,7 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -61,11 +61,10 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
Here, we wrote a C++ class wrapper that exposes the member functions
<tt class="literal">greet</tt> and <tt class="literal">set</tt>. Now, after building our module as a shared library, we
may use our class <tt class="literal">World</tt> in Python. Here's a sample Python session:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="string">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="char">'howdy'</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="char">
'howdy'</span></tt></pre>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
@@ -79,7 +78,6 @@ which is why we were able to write</p>
<p>
We may wish to wrap a class with a non-default constructor. Let us
build on our previous example:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> World</span><span class="special">
{</span><span class="identifier">
World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">):</span><span class="identifier"> msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span><span class="special"> {}</span><span class="comment"> // added constructor
@@ -144,18 +142,18 @@ Our C++ <tt class="literal">Var</tt> class and its data members can be exposed t
<p>
Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="char">'pi'</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special"> =</span><span class="number"> 3.14</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span><span class="string"> 'is around'</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="identifier">
pi</span><span class="keyword"> is</span><span class="identifier"> around</span><span class="number"> 3.14</span></tt></pre>
&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span><span class="char"> 'is around'</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="identifier">
pi</span><span class="identifier"> is</span><span class="identifier"> around</span><span class="number"> 3.14</span></tt></pre>
<p>
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span> while <tt class="literal">value</tt> is exposed
as <span class="bold"><b>read-write</b></span>.</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">name</span><span class="special"> =</span><span class="string"> 'e'</span><span class="comment"> # can't change name
</span><span class="identifier">Traceback</span><span class="special"> (</span><span class="identifier">most</span><span class="identifier"> recent</span><span class="identifier"> call</span><span class="identifier"> last</span><span class="special">):</span><span class="identifier">
File</span><span class="string"> "&lt;stdin&gt;"</span><span class="special">,</span><span class="identifier"> line</span><span class="number"> 1</span><span class="special">,</span><span class="keyword"> in</span>#<span class="identifier">
AttributeError</span><span class="special">:</span><span class="identifier"> can</span>#<span class="identifier">t</span><span class="identifier"> set</span><span class="identifier"> attribute</span></tt></pre>
<pre class="programlisting"><tt class="literal"> &gt;&gt;&gt; x.name = 'e' # can't change name
Traceback (most recent call last):
File "&lt;stdin&gt;", line 1, in ?
AttributeError: can't set attribute
</tt></pre>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
@@ -166,7 +164,6 @@ upon. Well designed classes that take advantage of encapsulation hide
the class' data members. The only way to access the class' data is
through access (getter/setter) functions. Access functions expose class
properties. Here's an example:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Num</span><span class="special">
{</span><span class="identifier">
Num</span><span class="special">();</span><span class="keyword">
@@ -184,17 +181,14 @@ attributes can just be a different syntax for a method call. Wrapping our
.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span></tt></pre>
<p>
And at last, in Python:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> Num</span><span class="special">()</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special"> =</span><span class="number"> 3.14</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special">
(</span><span class="number">3.14</span><span class="special">,</span><span class="number"> 3.14</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special"> =</span><span class="number"> 2.17</span><span class="comment"> # error!
</span></tt></pre>
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special"> =</span><span class="number"> 2.17</span> #<span class="identifier"> error</span><span class="special">!</span></tt></pre>
<p>
Take note that the class property <tt class="literal">rovalue</tt> is exposed as <span class="bold"><b>read-only</b></span>
since the <tt class="literal">rovalue</tt> setter member function is not passed in:</p>
<p></p>
<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"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span></tt></pre>
</div>
<div class="section" lang="en">
@@ -291,10 +285,13 @@ inherited <tt class="computeroutput"><span class="identifier">wrapper</span><spa
overridden in Python, easier.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br>
<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:<br><br><tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</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>
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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</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
@@ -308,8 +305,9 @@ Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span
function.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>member function and methods</b></span><br><br>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>member function and methods</b></span><p></p>
<p></p>
Python, like
many object oriented languages uses the term <span class="bold"><b>methods</b></span>. Methods
correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
@@ -321,7 +319,7 @@ correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
<p>
We've seen in the previous section how classes with pure virtual functions are
wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class wrapper</a>
wrapped using Boost.Python's <a href="../../../../v2//wrapper.html" target="_top">class wrapper</a>
facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions instead, the
mechanism is a bit different.</p>
<p>
@@ -358,11 +356,14 @@ Notice how we implemented <tt class="computeroutput"><span class="identifier">Ba
override for <tt class="computeroutput"><span class="identifier">f</span></tt>. If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/alert.png"></span> MSVC6/7 Workaround<p></p>
<p></p>
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<br><br><tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special">&lt;</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
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">&lt;</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*&gt;(</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>
Finally, exposing:</p>
@@ -376,10 +377,9 @@ forwarding function to its default implementation <tt class="literal">default_f<
special <tt class="literal">def</tt> function for this purpose.</p>
<p>
In Python, the results would be as expected:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="special">
&gt;&gt;&gt;</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="keyword"> 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="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><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> derived</span><span class="special"> =</span><span class="identifier"> Derived</span><span class="special">()</span></tt></pre>
@@ -396,7 +396,7 @@ Calling <tt class="literal">derived.f()</tt>:</p>
<div class="titlepage"><div><div><h3 class="title">
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
<a name="class_operators_special_functions.python_operators"></a><h2>
<a name="id447543"></a>Python Operators</h2>
<a name="id451830"></a>Python Operators</h2>
<p>
C is well known for the abundance of operators. C++ extends this to the
extremes by allowing operator overloading. Boost.Python takes advantage of
@@ -404,7 +404,6 @@ this and makes it easy to wrap C++ operator-powered classes.</p>
<p>
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators that take
on FilePos instances:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> FilePos</span><span class="special"> {</span><span class="comment"> /*...*/</span><span class="special"> };</span><span class="identifier">
FilePos</span><span class="keyword"> operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span><span class="keyword"> int</span><span class="special">);</span><span class="identifier">
@@ -434,20 +433,20 @@ you might need to interact with in an operator expression is (cheaply)
default-constructible. You can use <tt class="literal">other&lt;T&gt;()</tt> in place of an actual
<tt class="literal">T</tt> instance when writing "self expressions".</p>
<a name="class_operators_special_functions.special_methods"></a><h2>
<a name="id448230"></a>Special Methods</h2>
<a name="id452516"></a>Special Methods</h2>
<p>
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python supports all of the
standard special method names supported by real Python class instances. A
similar set of intuitive interfaces can also be used to wrap C++ functions
that correspond to these Python <span class="emphasis"><em>special functions</em></span>. Example:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> Rational</span><span class="special">
{</span><span class="keyword"> public</span><span class="special">:</span><span class="keyword"> operator</span><span class="keyword"> double</span><span class="special">()</span><span class="keyword"> const</span><span class="special">;</span><span class="special"> };</span><span class="identifier">
{</span><span class="keyword"> operator</span><span class="keyword"> double</span><span class="special">()</span><span class="keyword"> const</span><span class="special">;</span><span class="special"> };</span><span class="identifier">
Rational</span><span class="identifier"> pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span><span class="identifier"> Rational</span><span class="special">);</span><span class="identifier">
Rational</span><span class="identifier"> abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier">
ostream</span><span class="special">&amp;</span><span class="keyword"> operator</span><span class="special">&lt;&lt;(</span><span class="identifier">ostream</span><span class="special">&amp;,</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier">
class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;(</span><span class="string">"Rational"</span><span class="special">)</span><span class="special">
class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;()</span><span class="special">
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span><span class="comment"> // __float__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> other</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;))</span><span class="comment"> // __pow__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span><span class="comment"> // __abs__
@@ -457,16 +456,16 @@ class_</span><span class="special">&lt;</span><span class="identifier">Rational<
Need we say more?</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span> What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>?
Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt> requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt> to do its work (i.e.
<tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt> is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.</td></tr></tbody>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span> What is the business of <tt class="literal">operator&lt;&lt;</tt><tt class="literal">.def(str(self))</tt>?
Well, the method <tt class="literal">str</tt> requires the <tt class="literal">operator&lt;&lt;</tt> to do its work (i.e.
<tt class="literal">operator&lt;&lt;</tt> is used by the method defined by def(str(self)).</td></tr></tbody>
</table></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -42,27 +42,27 @@ overloading and default arguments.</p>
<p>
But before you do, you might want to fire up Python 2.2 or later and type
<tt class="literal">&gt;&gt;&gt; import this</tt>.</p>
<pre class="programlisting"><tt class="literal">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than <span class="bold"><b>right</b></span> now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
<pre class="programlisting"><tt class="literal"> &gt;&gt;&gt; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than <span class="bold"><b>right</b></span> now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</tt></pre>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
@@ -121,17 +121,15 @@ A reference to <tt class="literal">y.x</tt> is returned
</ol></div>
<p>
We could copy result into a new object:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span><span class="identifier"> z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span><span class="comment"> # Result disappears
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span><span class="comment"> # No crash, but still bad
</span><span class="number">3.14</span></tt></pre>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span><span class="identifier"> z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span> #<span class="identifier"> Result</span><span class="identifier"> disappears</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span>       #<span class="identifier"> No</span><span class="identifier"> crash</span><span class="special">,</span><span class="identifier"> but</span><span class="identifier"> still</span><span class="identifier"> bad</span><span class="number">
3.14</span></tt></pre>
<p>
This is not really our intent of our C++ interface. We've broken our
promise that the Python interface should reflect the C++ interface as
closely as possible.</p>
<p>
Our problems do not end there. Suppose Y is implemented as follows:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Y</span><span class="special">
{</span><span class="identifier">
X</span><span class="identifier"> x</span><span class="special">;</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">;</span><span class="keyword">
@@ -174,7 +172,7 @@ A reference to <tt class="literal">y.x</tt> is returned
<li><span class="bold"><b>BOOM!</b></span></li>
</ol></div>
<a name="call_policies.call_policies"></a><h2>
<a name="id449896"></a>Call Policies</h2>
<a name="id454162"></a>Call Policies</h2>
<p>
Call Policies may be used in situations such as the example detailed above.
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
@@ -206,44 +204,45 @@ Here is the list of predefined call policies. A complete reference detailing
these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.</p>
<div class="itemizedlist"><ul type="disc">
<li>
<span class="bold"><b>with_custodian_and_ward</b></span><br>
<span class="bold"><b>with_custodian_and_ward</b></span><p></p>
Ties lifetimes of the arguments
</li>
<li>
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><p></p>
Ties lifetimes of the arguments and results
</li>
<li>
<span class="bold"><b>return_internal_reference</b></span><br>
<span class="bold"><b>return_internal_reference</b></span><p></p>
Ties lifetime of one argument to that of result
</li>
<li>
<span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><br>
<span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><p></p>
</li>
<li>
<span class="bold"><b>reference_existing_object</b></span><br>
<span class="bold"><b>reference_existing_object</b></span><p></p>
naive (dangerous) approach
</li>
<li>
<span class="bold"><b>copy_const_reference</b></span><br>
<span class="bold"><b>copy_const_reference</b></span><p></p>
Boost.Python v1 approach
</li>
<li>
<span class="bold"><b>copy_non_const_reference</b></span><br>
<span class="bold"><b>copy_non_const_reference</b></span><p></p>
</li>
<li>
<span class="bold"><b>manage_new_object</b></span><br>
<span class="bold"><b>manage_new_object</b></span><p></p>
Adopt a pointer and hold the instance
</li>
</ul></div>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/smiley.png"></span><span class="bold"><b>Remember the Zen, Luke:</b></span><br><br>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/smiley.png"></span><span class="bold"><b>Remember the Zen, Luke:</b></span><p></p>
<p></p>
"Explicit is better than implicit"<br>
"Explicit is better than implicit"<p></p>
"In the face of ambiguity, refuse the temptation to guess"<br>
"In the face of ambiguity, refuse the temptation to guess"<p></p>
</td></tr></tbody>
</table></div>
</div>
@@ -336,7 +335,7 @@ are overloaded with a common sequence of initial arguments
</li>
</ul></div>
<a name="default_arguments.boost_python_function_overloads"></a><h2>
<a name="id451716"></a>BOOST_PYTHON_FUNCTION_OVERLOADS</h2>
<a name="id455979"></a>BOOST_PYTHON_FUNCTION_OVERLOADS</h2>
<p>
Boost.Python now has a way to make it easier. For instance, given a function:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">int</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> b</span><span class="special"> =</span><span class="number"> 1</span><span class="special">,</span><span class="keyword"> unsigned</span><span class="identifier"> c</span><span class="special"> =</span><span class="number"> 2</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> d</span><span class="special"> =</span><span class="number"> 3</span><span class="special">)</span><span class="special">
@@ -355,7 +354,7 @@ and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
automatically add all the foo variants for us:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="identifier"> foo_overloads</span><span class="special">());</span></tt></pre>
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
<a name="id451995"></a>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2>
<a name="id456259"></a>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2>
<p>
Objects here, objects there, objects here there everywhere. More frequently
than anything else, we need to expose member functions of our classes to
@@ -387,7 +386,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads reference</a>
for details.</p>
<a name="default_arguments.init_and_optional"></a><h2>
<a name="id452323"></a>init and optional</h2>
<a name="id456586"></a>init and optional</h2>
<p>
A similar facility is provided for class constructors, again, with
default arguments or a sequence of overloads. Remember <tt class="literal">init&lt;...&gt;</tt>? For example,
@@ -442,7 +441,7 @@ Then...</p>
Notice though that we have a situation now where we have a minimum of zero
(0) arguments and a maximum of 3 arguments.</p>
<a name="auto_overloading.manual_wrapping"></a><h2>
<a name="id452969"></a>Manual Wrapping</h2>
<a name="id457233"></a>Manual Wrapping</h2>
<p>
It is important to emphasize however that <span class="bold"><b>the overloaded functions must
have a common sequence of initial arguments</b></span>. Otherwise, our scheme above
@@ -470,7 +469,7 @@ Then...</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -26,7 +26,7 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
<a name="hello.from_start_to_finish"></a><h2>
<a name="id374047"></a>From Start To Finish</h2>
<a name="id446728"></a>From Start To Finish</h2>
<p>
Now the first thing you'd want to do is to build the Hello World module and
try it for yourself in Python. In this section, we shall outline the steps
@@ -34,12 +34,14 @@ necessary to achieve that. We shall use the build tool that comes bundled
with every boost distribution: <span class="bold"><b>bjam</b></span>.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><br><br>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><p></p>
<p></p>
Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as "the one and only way".
There are of course other build tools apart from <tt class="literal">bjam</tt>.<br><br>
There are of course other build tools apart from <tt class="literal">bjam</tt>.<p></p>
<p></p>
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
@@ -93,108 +95,93 @@ the command line. Pre-built Boost.Jam executables are available for most
platforms. The complete list of Bjam executables can be found
<a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.</p>
<a name="hello.let_s_jam_"></a><h2>
<a name="id372653"></a>Let's Jam!</h2>
<a name="id377058"></a>Let's Jam!</h2>
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
<p>
Here is our minimalist Jamfile:</p>
<pre class="programlisting"><tt class="literal"># This is the top of our own project tree
project-root ;
<pre class="programlisting"><tt class="literal"> subproject libs/python/example/tutorial ;
import python ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
extension hello # Declare a Python extension called hello
: hello.cpp # source
# requirements and dependencies for Boost.Python extensions
&lt;template&gt;@boost/libs/python/build/extension
;
extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</tt></pre>
<p>
First, we need to specify our location. You may place your project anywhere.
<tt class="literal">project-root</tt> allows you to do that.</p>
<pre class="programlisting"><tt class="literal">project-root ;
First, we need to specify our location in the boost project hierarchy.
It so happens that the tutorial example is located in <tt class="literal">/libs/python/example/tutorial</tt>.
Thus:</p>
<pre class="programlisting"><tt class="literal"> subproject libs/python/example/tutorial ;
</tt></pre>
<p>
By doing so, you'll need a Jamrules file. Simply copy the one in the
<a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a> and tweak
the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost root directory is. The file
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you can follow.</p>
<p>
Then we will import the definitions needed by Python modules:</p>
<pre class="programlisting"><tt class="literal">import python ;
Then we will include the definitions needed by Python modules:</p>
<pre class="programlisting"><tt class="literal"> SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
</tt></pre>
<p>
Finally we declare our <tt class="literal">hello</tt> extension:</p>
<pre class="programlisting"><tt class="literal">extension hello # Declare a Python extension called hello
: hello.cpp # source
# requirements and dependencies for Boost.Python extensions
&lt;template&gt;@boost/libs/python/build/extension
;
<pre class="programlisting"><tt class="literal"> extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</tt></pre>
<p>
The last part tells BJam that we are depending on the Boost Python Library.</p>
<a name="hello.running_bjam"></a><h2>
<a name="id372775"></a>Running bjam</h2>
<a name="id377153"></a>Running bjam</h2>
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line interpreter.</p>
<div class="blockquote"><blockquote class="blockquote"><p>Start it up.</p></blockquote></div>
<p>
Make sure that the environment is set so that we can invoke the C++
compiler. With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
file. For instance:</p>
<pre class="programlisting"><tt class="literal">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
</tt></pre>
<pre class="programlisting"><tt class="literal"><span class="identifier">C</span><span class="special">:\</span><span class="identifier">Program</span><span class="identifier"> Files</span><span class="special">\</span><span class="identifier">Microsoft</span><span class="identifier"> Visual</span><span class="identifier"> Studio</span><span class="special">\</span><span class="identifier">VC98</span><span class="special">\</span><span class="identifier">bin</span><span class="special">\</span><span class="identifier">Vcvars32</span><span class="special">.</span><span class="identifier">bat</span></tt></pre>
<p>
Some environment variables will have to be setup for proper building of our
Python modules. Example:</p>
<pre class="programlisting"><tt class="literal">set PYTHON_ROOT=c:/dev/tools/python
set PYTHON_VERSION=2.2
</tt></pre>
<pre class="programlisting"><tt class="literal"><span class="identifier">set</span><span class="identifier"> PYTHON_ROOT</span><span class="special">=</span><span class="identifier">c</span><span class="special">:/</span><span class="identifier">dev</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">python</span><span class="identifier">
set</span><span class="identifier"> PYTHON_VERSION</span><span class="special">=</span><span class="number">2.2</span></tt></pre>
<p>
The above assumes that the Python installation is in <tt class="literal">c:/dev/tools/python</tt>
and that we are using Python version 2.2. You'll have to tweak these
and that we are using Python version 2.2. You'll have to tweak this path
appropriately.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/tip.png"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1",
even if that's the version you have.</td></tr></tbody>
</table></div>
<p>
Take note that you may also do that through the Jamrules file we put in
our project as detailed above. The file
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you
can follow.</p>
<p>
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamfile"</tt> is situated.</p>
<p>
Finally:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">bjam</span><span class="special"> -</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span></tt></pre>
<pre class="programlisting"><tt class="literal"><span class="identifier">bjam</span><span class="special"> -</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">msvc</span></tt></pre>
<p>
We are again assuming that we are using Microsoft Visual C++ version 7.1. 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
<a href="../../../../../../../tools/build/index.html" target="_top">Building Boost Libraries</a> for
further details.</p>
<p>
It should be building now:</p>
<pre class="programlisting"><tt class="literal">cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
<pre class="programlisting"><tt class="literal"> cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
</tt></pre>
<p>
And so on... Finally:</p>
<pre class="programlisting"><tt class="literal">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
hello.cpp
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
...updated 31 targets...
<pre class="programlisting"><tt class="literal"> vc-C++ ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.obj
hello.cpp
vc-Link ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.pyd ........\libs\python\example\tutorial\bin\
hello.pyd\msvc\debug\runtime-link-dynamic\hello.lib
Creating library ........\libs\python\example\tutorial\bin\hello.pyd\
msvc\debug\runtime-link-dynamic\hello.lib and object ........\libs\python\
example\tutorial\bin\hello.pyd\msvc\debug\runtime-link-dynamic\hello.exp
...updated 40 targets...
</tt></pre>
<p>
If all is well, you should now have:</p>
@@ -218,22 +205,22 @@ hello.so
</ul></div>
<p>
if you are on Unix.</p>
<p><tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be found somewhere in your project's
<tt class="literal">bin</tt> directory. After a successful build, you can just link in these DLLs with
the Python interpreter. In Windows for example, you can simply put these libraries
inside the directory where the Python executable is.</p>
<p><tt class="literal">boost_python.dll</tt> can be found somewhere in <tt class="literal">libs\python\build\bin</tt>
while <tt class="literal">hello.pyd</tt> can be found somewhere in
<tt class="literal">libs\python\example\tutorial\bin</tt>. After a successful build, you can just
link in these DLLs with the Python interpreter. In Windows for example, you
can simply put these libraries inside the directory where the Python
executable is.</p>
<p>
You may now fire up Python and run our hello module:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
hello</span><span class="special">,</span><span class="identifier"> world</span></tt></pre>
<p></p>
<div class="blockquote"><blockquote class="blockquote"><p><span class="bold"><b>There you go... Have fun!</b></span></p></blockquote></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -54,20 +54,17 @@ Raises StopIteration exception at end
</ul></div>
<p>
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y in x...</b></span></tt> is as follows:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">iter</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span><span class="comment"> # get iterator
</span><span class="keyword">try</span><span class="special">:</span><span class="keyword">
<pre class="programlisting"><tt class="literal"><span class="identifier">iter</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span>         #<span class="identifier"> get</span><span class="identifier"> iterator</span><span class="keyword">
try</span><span class="special">:</span><span class="keyword">
while</span><span class="number"> 1</span><span class="special">:</span><span class="identifier">
y</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span><span class="comment"> # get each item
</span><span class="special"> ...</span><span class="comment"> # process y
</span><span class="keyword">except</span><span class="identifier"> StopIteration</span><span class="special">:</span><span class="keyword"> pass</span><span class="comment"> # iterator exhausted
</span></tt></pre>
y</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span>         #<span class="identifier"> get</span><span class="identifier"> each</span><span class="identifier"> item</span><span class="special">
...</span>                     #<span class="identifier"> process</span><span class="identifier"> y</span><span class="identifier">
except</span><span class="identifier"> StopIteration</span><span class="special">:</span><span class="identifier"> pass</span>  #<span class="identifier"> iterator</span><span class="identifier"> exhausted</span></tt></pre>
<p>
Boost.Python provides some mechanisms to make C++ iterators play along
nicely as Python iterators. What we need to do is to produce
appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that is compatible
appropriate <span class="underline">_iter</span>_ function from C++ iterators that is compatible
with the Python iteration protocol. For example:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> get_iterator</span><span class="special"> =</span><span class="identifier"> iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span><span class="special"> &gt;();</span><span class="identifier">
object</span><span class="identifier"> iter</span><span class="special"> =</span><span class="identifier"> get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span><span class="identifier">
object</span><span class="identifier"> first</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span></tt></pre>
@@ -108,22 +105,20 @@ with &amp;T::begin, &amp;T::end.</p>
<p>
Let's put this into action... Here's an example from some hypothetical
bogon Particle accelerator code:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">f</span><span class="special"> =</span><span class="identifier"> Field</span><span class="special">()</span><span class="keyword">
for</span><span class="identifier"> x</span><span class="keyword"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span><span class="identifier">
for</span><span class="identifier"> x</span><span class="identifier"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span><span class="identifier">
smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span><span class="keyword">
for</span><span class="identifier"> y</span><span class="keyword"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span><span class="identifier">
for</span><span class="identifier"> y</span><span class="identifier"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span><span class="identifier">
count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span></tt></pre>
<p>
Now, our C++ Wrapper:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="string">"Field"</span><span class="special">)</span><span class="special">
.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"pions"</span><span class="special">,</span><span class="identifier"> range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span><span class="special">
.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span><span class="identifier"> range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span></tt></pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -53,19 +53,17 @@ Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>.
<tt class="literal">object</tt>s can in fact be explicitly constructed from any C++ object.</p>
<p>
To illustrate, this Python code snippet:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> y</span><span class="special">):</span><span class="keyword">
if</span><span class="special"> (</span><span class="identifier">y</span><span class="special"> ==</span><span class="string"> 'foo'</span><span class="special">):</span><span class="identifier">
x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span><span class="special"> =</span><span class="string"> 'bar'</span><span class="keyword">
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> y</span><span class="special">):</span><span class="keyword">
if</span><span class="special"> (</span><span class="identifier">y</span><span class="special"> ==</span><span class="char"> 'foo'</span><span class="special">):</span><span class="identifier">
x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span><span class="special"> =</span><span class="char"> 'bar'</span><span class="keyword">
else</span><span class="special">:</span><span class="identifier">
x</span><span class="special">.</span><span class="identifier">items</span><span class="special"> +=</span><span class="identifier"> y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier"> x</span><span class="special">)</span><span class="keyword">
return</span><span class="identifier"> x</span><span class="keyword">
return</span><span class="identifier"> x</span><span class="identifier">
def</span><span class="identifier"> getfunc</span><span class="special">():</span><span class="keyword">
return</span><span class="identifier"> f</span><span class="special">;</span></tt></pre>
<p>
Can be rewritten in C++ using Boost.Python facilities this way:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">object</span><span class="identifier"> x</span><span class="special">,</span><span class="identifier"> object</span><span class="identifier"> y</span><span class="special">)</span><span class="special"> {</span><span class="keyword">
if</span><span class="special"> (</span><span class="identifier">y</span><span class="special"> ==</span><span class="string"> "foo"</span><span class="special">)</span><span class="identifier">
x</span><span class="special">.</span><span class="identifier">slice</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">7</span><span class="special">)</span><span class="special"> =</span><span class="string"> "bar"</span><span class="special">;</span><span class="keyword">
@@ -137,27 +135,18 @@ member functions.</p>
<p>
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format" % x,y,z</tt>
in Python, which is useful since there's no easy way to do that in std C++.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>Beware</b></span> the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.
</td></tr></tbody>
</table></div>
<p><span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>Beware</b></span> the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.</p>
<p>
Python:
</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special"> =</span><span class="identifier"> dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special">)</span><span class="comment"> # copies x.__dict__
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span><span class="comment"> # modifies the copy
</span></tt></pre>
Python:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special"> =</span><span class="identifier"> dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__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="special">
&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span>            #<span class="identifier"> modifies</span><span class="identifier"> the</span><span class="identifier"> copy</span></tt></pre>
<p>
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="comment"> // copies x.__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="comment"> // modifies the copy
</span></tt></pre>
C++:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">dict</span><span class="identifier"> d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span>  #<span class="identifier"> copies</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="identifier">
d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span><span class="special"> =</span><span class="number"> 3</span><span class="special">;</span>           #<span class="identifier"> modifies</span><span class="identifier"> the</span><span class="identifier"> copy</span></tt></pre>
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
<a name="id454735"></a>class_&lt;T&gt; as objects</h2>
<a name="id459043"></a>class_&lt;T&gt; as objects</h2>
<p>
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_&lt;T&gt;</tt> may
also be one of these types! The following code snippet wraps the class
@@ -188,15 +177,16 @@ we wanted to do above can be achieved by writing:</p>
Vec2</span><span class="special">&amp;</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;(</span><span class="identifier">o</span><span class="special">);</span><span class="identifier">
assert</span><span class="special">(</span><span class="identifier">l</span><span class="special"> ==</span><span class="identifier"> v</span><span class="special">.</span><span class="identifier">length</span><span class="special">());</span></tt></pre>
<p>
The first line attempts to extract the "length" attribute of the Boost.Python
<tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span> the <tt class="literal">Vec2</tt> object from held
by the Boost.Python <tt class="literal">object</tt>.</p>
The first line attempts to extract the "length" attribute of the
Boost.Python <tt class="literal">object</tt><tt class="literal">o</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span> the
<tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt><tt class="literal">o</tt>.</p>
<p>
Take note that we said "attempt to" above. What if the Boost.Python <tt class="literal">object</tt>
does not really hold a <tt class="literal">Vec2</tt> type? This is certainly a possibility considering
the dynamic nature of Python <tt class="literal">object</tt>s. To be on the safe side, if the C++ type
can't be extracted, an appropriate exception is thrown. To avoid an exception,
we need to test for extractibility:</p>
Take note that we said "attempt to" above. What if the Boost.Python
<tt class="literal">object</tt><tt class="literal">o</tt> does not really hold a <tt class="literal">Vec2</tt> type? This is certainly
a possibility considering the dynamic nature of Python <tt class="literal">object</tt>s. To
be on the safe side, if the C++ type can't be extracted, an
appropriate exception is thrown. To avoid an exception, we need to
test for extractibility:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;</span><span class="identifier"> x</span><span class="special">(</span><span class="identifier">o</span><span class="special">);</span><span class="keyword">
if</span><span class="special"> (</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">check</span><span class="special">())</span><span class="special"> {</span><span class="identifier">
Vec2</span><span class="special">&amp;</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">();</span><span class="special"> ...</span></tt></pre>
@@ -229,8 +219,9 @@ creates a Python class derived from Python's <tt class="literal">int</tt> type w
associated with the C++ type passed as its first parameter.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>what is a scope?</b></span><br><br>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>what is a scope?</b></span><p></p>
<p></p>
The scope is a class that has an
associated global Python object which controls the Python namespace in
which new extension classes and wrapped functions will be defined as
@@ -238,13 +229,11 @@ attributes. Details can be found <a href="../../../../v2/scope.html" target="_to
</table></div>
<p>
You can access those values in Python as</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span><span class="identifier">
my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span></tt></pre>
<p>
where my_module is the module where the enum is declared. You can also
create a new scope around a class:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">scope</span><span class="identifier"> in_X</span><span class="special"> =</span><span class="identifier"> class_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;(</span><span class="string">"X"</span><span class="special">)</span><span class="special">
.</span><span class="identifier">def</span><span class="special">(</span><span class="special"> ...</span><span class="special"> )</span><span class="special">
.</span><span class="identifier">def</span><span class="special">(</span><span class="special"> ...</span><span class="special"> )</span><span class="special">
@@ -259,7 +248,7 @@ create a new scope around a class:</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -12,7 +12,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">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="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -83,31 +83,30 @@ Compiling these files will generate the following Python extensions:
<tt class="literal">core.pyd</tt>, <tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span> The extension <tt class="literal">.pyd</tt> is used for python extension modules, which
are just shared libraries. Using the default for your system, like <tt class="literal">.so</tt> for
Unix and <tt class="literal">.dll</tt> for Windows, works just as well.</td></tr></tbody>
</table></div>
<p>
Now, we create this directory structure for our Python package:</p>
<pre class="programlisting"><tt class="literal">sounds/
__init__.py
core.pyd
filters.pyd
io.pyd
<pre class="programlisting"><tt class="literal"> sounds/
<span class="underline">_init</span>_.py
core.pyd
filters.pyd
io.pyd
</tt></pre>
<p>
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory <tt class="literal">sounds/</tt> is
The file <tt class="literal"><span class="underline">_init</span>_.py</tt> is what tells Python that the directory <tt class="literal">sounds/</tt> is
actually a Python package. It can be a empty file, but can also perform some
magic, that will be shown later.</p>
<p>
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt> into his
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
and fire up the interpreter:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> sound</span><span class="special"> =</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">open</span><span class="special">(</span><span class="string">'file.mp3'</span><span class="special">)</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> sound</span><span class="special"> =</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">open</span><span class="special">(</span><span class="char">'file.mp3'</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> new_sound</span><span class="special"> =</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">,</span><span class="number"> 1.0</span><span class="special">)</span></tt></pre>
<p>
Nice heh?</p>
@@ -121,7 +120,6 @@ it.</p>
<p>
If we want this flexibility, we will have to complicate our package hierarchy a
little. First, we will have to change the name of the extension modules:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="comment">/* file core.cpp */</span><span class="identifier">
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_core</span><span class="special">)</span><span class="special">
{</span><span class="special">
@@ -132,35 +130,34 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
Note that we added an underscore to the module name. The filename will have to
be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same to the other extension modules.
Now, we change our package hierarchy like so:</p>
<pre class="programlisting"><tt class="literal">sounds/
__init__.py
core/
__init__.py
_core.pyd
filters/
__init__.py
_filters.pyd
io/
__init__.py
_io.pyd
<pre class="programlisting"><tt class="literal"> sounds/
<span class="underline">_init</span>_.py
core/
<span class="underline">_init</span>_.py
_core.pyd
filters/
<span class="underline">_init</span>_.py
_filters.pyd
io/
<span class="underline">_init</span>_.py
_io.pyd
</tt></pre>
<p>
Note that we created a directory for each extension module, and added a
__init__.py to each one. But if we leave it that way, the user will have to
<span class="underline">_init</span>_.py to each one. But if we leave it that way, the user will have to
access the functions in the core module with this syntax:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span></tt></pre>
<p>
which is not what we want. But here enters the <tt class="literal">__init__.py</tt> magic: everything
that is brought to the <tt class="literal">__init__.py</tt> namespace can be accessed directly by the
which is not what we want. But here enters the <tt class="literal"><span class="underline">_init</span>_.py</tt> magic: everything
that is brought to the <tt class="literal"><span class="underline">_init</span>_.py</tt> namespace can be accessed directly by the
user. So, all we have to do is bring the entire namespace from <tt class="literal">_core.pyd</tt>
to <tt class="literal">core/__init__.py</tt>. So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> _core</span><span class="keyword"> import</span><span class="special"> *</span></tt></pre>
to <tt class="literal">core/<span class="underline">_init</span><span class="underline">.py]. So add this line of code to [^sounds/core/</span><span class="underline">init</span>_.py</tt>:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">from</span><span class="identifier"> _core</span><span class="identifier"> import</span><span class="special"> *</span></tt></pre>
<p>
We do the same for the other packages. Now the user accesses the functions and
classes in the extension modules like before:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span></tt></pre>
<p>
with the additional benefit that we can easily add pure Python functions to
@@ -169,18 +166,18 @@ function and a Python function. Let's add a <span class="emphasis"><em>pure</em>
<tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt> package. This function applies both the
<tt class="literal">echo</tt> and <tt class="literal">noise</tt> filters in sequence in the given <tt class="literal">sound</tt> object. We
create a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our function:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">import</span><span class="identifier"> _filters</span><span class="keyword">
<pre class="programlisting"><tt class="literal"><span class="identifier">import</span><span class="identifier"> _filters</span><span class="identifier">
def</span><span class="identifier"> echo_noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">):</span><span class="identifier">
s</span><span class="special"> =</span><span class="identifier"> _filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span><span class="identifier">
s</span><span class="special"> =</span><span class="identifier"> _filters</span><span class="special">.</span><span class="identifier">noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span><span class="keyword">
return</span><span class="identifier"> s</span></tt></pre>
<p>
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:</p>
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> echo_noise</span><span class="keyword"> import</span><span class="identifier"> echo_noise</span></tt></pre>
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span><span class="underline">_init</span>_.py</tt>:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">from</span><span class="identifier"> echo_noise</span><span class="identifier"> import</span><span class="identifier"> echo_noise</span></tt></pre>
<p>
And that's it. The user now accesses this function like any other function
from the <tt class="literal">filters</tt> package:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo_noise</span><span class="special">(...)</span></tt></pre>
</div>
<div class="section" lang="en">
@@ -189,16 +186,16 @@ from the <tt class="literal">filters</tt> package:</p>
<p>
Thanks to Python's flexibility, you can easily add new methods to a class,
even after it was already created:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> class</span><span class="identifier"> C</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span><span class="keyword"> pass</span><span class="special">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> class</span><span class="identifier"> C</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span><span class="identifier"> pass</span><span class="special">
&gt;&gt;&gt;</span><span class="special">
&gt;&gt;&gt;</span><span class="comment"> # a regular function
</span><span class="special">&gt;&gt;&gt;</span><span class="keyword"> def</span><span class="identifier"> C_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> return</span><span class="string"> 'A C instance!'</span><span class="special">
&gt;&gt;&gt;</span> #<span class="identifier"> a</span><span class="identifier"> regular</span><span class="identifier"> function</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> def</span><span class="identifier"> C_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> return</span><span class="char"> 'A C instance!'</span><span class="special">
&gt;&gt;&gt;</span><span class="special">
&gt;&gt;&gt;</span><span class="comment"> # now we turn it in a member function
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> C</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> C_str</span><span class="special">
&gt;&gt;&gt;</span> #<span class="identifier"> now</span><span class="identifier"> we</span><span class="identifier"> turn</span><span class="identifier"> it</span><span class="identifier"> in</span><span class="identifier"> a</span><span class="identifier"> member</span><span class="identifier"> function</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> C</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> C_str</span><span class="special">
&gt;&gt;&gt;</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> c</span><span class="special"> =</span><span class="identifier"> C</span><span class="special">()</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> c</span><span class="identifier">
&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> c</span><span class="identifier">
A</span><span class="identifier"> C</span><span class="identifier"> instance</span><span class="special">!</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> C_str</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span><span class="identifier">
A</span><span class="identifier"> C</span><span class="identifier"> instance</span><span class="special">!</span></tt></pre>
@@ -207,7 +204,6 @@ Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png"
<p>
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <tt class="literal">point</tt> in C++:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> point</span><span class="special"> {...};</span><span class="identifier">
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span><span class="special">
@@ -217,16 +213,15 @@ BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier"
<p>
If we are using the technique from the previous session,
<a href="techniques.html#python.creating_packages" title="Creating Packages">Creating Packages</a>, we can code directly
into <tt class="literal">geom/__init__.py</tt>:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> _geom</span><span class="keyword"> import</span><span class="special"> *</span><span class="comment">
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>
# a regular function
</span><span class="keyword">def</span><span class="identifier"> point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword">
return</span><span class="identifier"> str</span><span class="special">((</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">))</span><span class="comment">
#<span class="identifier"> a</span><span class="identifier"> regular</span><span class="identifier"> function</span><span class="identifier">
def</span><span class="identifier"> point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword">
return</span><span class="identifier"> str</span><span class="special">((</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">))</span>
# now we turn it into a member function
</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> point_str</span></tt></pre>
#<span class="identifier"> now</span><span class="identifier"> we</span><span class="identifier"> turn</span><span class="identifier"> it</span><span class="identifier"> into</span><span class="identifier"> a</span><span class="identifier"> member</span><span class="identifier"> function</span><span class="identifier">
point</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> point_str</span></tt></pre>
<p><span class="bold"><b>All</b></span> point instances created from C++ will also have this member function!
This technique has several advantages:</p>
<div class="itemizedlist"><ul type="disc">
@@ -246,34 +241,35 @@ Rapid prototyping (you can move the code to C++ if required without changing the
<p>
You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that "injects" methods in other classes.</p>
<pre class="programlisting"><tt class="literal"><span class="comment"># The one Boost.Python uses for all wrapped classes.
# You can use here any class exported by Boost instead of "point"
</span><span class="identifier">BoostPythonMetaclass</span><span class="special"> =</span><span class="identifier"> point</span><span class="special">.</span><span class="identifier">__class__</span><span class="keyword">
<pre class="programlisting"><tt class="literal">
#<span class="identifier"> The</span><span class="identifier"> one</span><span class="identifier"> Boost</span><span class="special">.</span><span class="identifier">Python</span><span class="identifier"> uses</span><span class="keyword"> for</span><span class="identifier"> all</span><span class="identifier"> wrapped</span><span class="identifier"> classes</span><span class="special">.</span>
#<span class="identifier"> You</span><span class="identifier"> can</span><span class="identifier"> use</span><span class="identifier"> here</span><span class="identifier"> any</span><span class="keyword"> class</span><span class="identifier"> exported</span><span class="identifier"> by</span><span class="identifier"> Boost</span><span class="identifier"> instead</span><span class="identifier"> of</span><span class="string"> "point"</span><span class="identifier">
BoostPythonMetaclass</span><span class="special"> =</span><span class="identifier"> point</span><span class="special">.</span><span class="identifier">__class__</span><span class="keyword">
class</span><span class="identifier"> injector</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span><span class="keyword">
class</span><span class="identifier"> __metaclass__</span><span class="special">(</span><span class="identifier">BoostPythonMetaclass</span><span class="special">):</span><span class="keyword">
class</span><span class="identifier"> __metaclass__</span><span class="special">(</span><span class="identifier">BoostPythonMetaclass</span><span class="special">):</span><span class="identifier">
def</span><span class="identifier"> __init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> name</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">,</span><span class="identifier"> dict</span><span class="special">):</span><span class="keyword">
for</span><span class="identifier"> b</span><span class="keyword"> in</span><span class="identifier"> bases</span><span class="special">:</span><span class="keyword">
if</span><span class="identifier"> type</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span><span class="keyword"> not</span><span class="keyword"> in</span><span class="special"> (</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> type</span><span class="special">):</span><span class="keyword">
for</span><span class="identifier"> k</span><span class="special">,</span><span class="identifier">v</span><span class="keyword"> in</span><span class="identifier"> dict</span><span class="special">.</span><span class="identifier">items</span><span class="special">():</span><span class="identifier">
for</span><span class="identifier"> b</span><span class="identifier"> in</span><span class="identifier"> bases</span><span class="special">:</span><span class="keyword">
if</span><span class="identifier"> type</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span><span class="keyword"> not</span><span class="identifier"> in</span><span class="special"> (</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> type</span><span class="special">):</span><span class="keyword">
for</span><span class="identifier"> k</span><span class="special">,</span><span class="identifier">v</span><span class="identifier"> in</span><span class="identifier"> dict</span><span class="special">.</span><span class="identifier">items</span><span class="special">():</span><span class="identifier">
setattr</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span><span class="special">)</span><span class="keyword">
return</span><span class="identifier"> type</span><span class="special">.</span><span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> name</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">,</span><span class="identifier"> dict</span><span class="special">)</span><span class="comment">
return</span><span class="identifier"> type</span><span class="special">.</span><span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> name</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">,</span><span class="identifier"> dict</span><span class="special">)</span>
# inject some methods in the point foo
</span><span class="keyword">class</span><span class="identifier"> more_point</span><span class="special">(</span><span class="identifier">injector</span><span class="special">,</span><span class="identifier"> point</span><span class="special">):</span><span class="keyword">
#<span class="identifier"> inject</span><span class="identifier"> some</span><span class="identifier"> methods</span><span class="identifier"> in</span><span class="identifier"> the</span><span class="identifier"> point</span><span class="identifier"> foo</span><span class="keyword">
class</span><span class="identifier"> more_point</span><span class="special">(</span><span class="identifier">injector</span><span class="special">,</span><span class="identifier"> point</span><span class="special">):</span><span class="identifier">
def</span><span class="identifier"> __repr__</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword">
return</span><span class="string"> 'Point(x=%s, y=%s)'</span><span class="special"> %</span><span class="special"> (</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">)</span><span class="keyword">
def</span><span class="identifier"> foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword">
print</span><span class="string"> 'foo!'</span></tt></pre>
return</span><span class="char"> 'Point(x=%s, y=%s)'</span><span class="special"> %</span><span class="special"> (</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">)</span><span class="identifier">
def</span><span class="identifier"> foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="identifier">
print</span><span class="char"> 'foo!'</span></tt></pre>
<p>
Now let's see how it got:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> point</span><span class="special">()</span><span class="identifier">
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> point</span><span class="special">()</span><span class="identifier">
Point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">10</span><span class="special">,</span><span class="identifier"> y</span><span class="special">=</span><span class="number">10</span><span class="special">)</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> point</span><span class="special">().</span><span class="identifier">foo</span><span class="special">()</span><span class="identifier">
foo</span><span class="special">!</span></tt></pre>
<p>
Another useful idea is to replace constructors with factory functions:</p>
<pre class="programlisting"><tt class="literal"><span class="identifier">_point</span><span class="special"> =</span><span class="identifier"> point</span><span class="keyword">
<pre class="programlisting"><tt class="literal"><span class="identifier">_point</span><span class="special"> =</span><span class="identifier"> point</span><span class="identifier">
def</span><span class="identifier"> point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">0</span><span class="special">,</span><span class="identifier"> y</span><span class="special">=</span><span class="number">0</span><span class="special">):</span><span class="keyword">
return</span><span class="identifier"> _point</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> y</span><span class="special">)</span></tt></pre>
@@ -291,7 +287,6 @@ If you have ever exported a lot of classes, you know that it takes quite a good
time to compile the Boost.Python wrappers. Plus the memory consumption can
easily become too high. If this is causing you problems, you can split the
class_ definitions in multiple files:</p>
<p></p>
<pre class="programlisting"><tt class="literal"><span class="comment">/* file point.cpp */</span><span class="preprocessor">
#include</span><span class="special"> &lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span><span class="preprocessor">
#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword">
@@ -340,14 +335,14 @@ 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.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
take a look at the <tt class="literal">--multiple</tt> option, that generates the wrappers in
various files as demonstrated here.</td></tr></tbody>
</table></div>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td class="blurb">
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span> This method is useful too if you are getting the error message
<span class="emphasis"><em>"fatal error C1204:Compiler limit:internal structure overflow"</em></span> when compiling
a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
@@ -356,7 +351,7 @@ a large source file, as explained in the <a href="../../../../v2/faq.html#c1204"
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

@@ -1,7 +1,7 @@
[library python
[version 1.0]
[authors [de Guzman, Joel], [Abrahams, David]]
[copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams]
[copyright 2002 2003 2004 Joel de Guzman, David Abrahams]
[category inter-language support]
[purpose
Reflects C++ classes and functions into Python
@@ -21,7 +21,6 @@
[def __alert__ [$images/alert.png]]
[def __tip__ [$images/tip.png]]
[def :-) [$images/smiley.png]]
[def __jam__ [$images/jam.png]]
[section QuickStart]
@@ -59,14 +58,10 @@ can be exposed to Python by writing a Boost.Python wrapper:
That's it. We're done. We can now build this as a shared library. The
resulting DLL is now visible to Python. Here's a sample Python session:
[python]
>>> import hello
>>> print hello.greet()
hello, world
[c++]
[:['[*Next stop... Building your Hello World module from start to finish...]]]
[endsect]
@@ -120,54 +115,46 @@ platforms. The complete list of Bjam executables can be found
[@http://sourceforge.net/project/showfiles.php?group_id=7586 here].
[h2 Let's Jam!]
__jam__
[$../images/jam.png]
Here is our minimalist Jamfile:
[pre
# This is the top of our own project tree
project-root ;
subproject libs/python/example/tutorial ;
import python ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
extension hello # Declare a Python extension called hello
: hello.cpp # source
# requirements and dependencies for Boost.Python extensions
<template>@boost/libs/python/build/extension
;
extension hello # Declare a Python extension called hello
: hello.cpp # source
<dll>../../build/boost_python # dependencies
;
]
First, we need to specify our location. You may place your project anywhere.
[^project-root] allows you to do that.
First, we need to specify our location in the boost project hierarchy.
It so happens that the tutorial example is located in [^/libs/python/example/tutorial].
Thus:
[pre
project-root ;
subproject libs/python/example/tutorial ;
]
By doing so, you'll need a Jamrules file. Simply copy the one in the
[@../../../../example/tutorial/Jamrules example/tutorial directory] and tweak
the [^path-global BOOST_ROOT] to where your boost root directory is. The file
has [@../../../../example/tutorial/Jamrules detailed instructions] you can follow.
Then we will import the definitions needed by Python modules:
Then we will include the definitions needed by Python modules:
[pre
import python ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
]
Finally we declare our [^hello] extension:
[pre
extension hello # Declare a Python extension called hello
: hello.cpp # source
# requirements and dependencies for Boost.Python extensions
<template>@boost/libs/python/build/extension
;
extension hello # Declare a Python extension called hello
: hello.cpp # source
<dll>../../build/boost_python # dependencies
;
]
The last part tells BJam that we are depending on the Boost Python Library.
[h2 Running bjam]
['bjam] is run using your operating system's command line interpreter.
@@ -178,38 +165,29 @@ Make sure that the environment is set so that we can invoke the C++
compiler. With MSVC, that would mean running the [^Vcvars32.bat] batch
file. For instance:
[pre
C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
]
C:\Program Files\Microsoft Visual Studio\VC98\bin\Vcvars32.bat
Some environment variables will have to be setup for proper building of our
Python modules. Example:
[pre
set PYTHON_ROOT=c:/dev/tools/python
set PYTHON_VERSION=2.2
]
set PYTHON_ROOT=c:/dev/tools/python
set PYTHON_VERSION=2.2
The above assumes that the Python installation is in [^c:/dev/tools/python]
and that we are using Python version 2.2. You'll have to tweak these
and that we are using Python version 2.2. You'll have to tweak this path
appropriately.
[blurb __tip__ Be sure not to include a third number, e.g. [*not] "2.2.1",
even if that's the version you have.]
Take note that you may also do that through the Jamrules file we put in
our project as detailed above. The file
has [@../../../../example/tutorial/Jamrules detailed instructions] you
can follow.
Now we are ready... Be sure to [^cd] to [^libs/python/example/tutorial]
where the tutorial [^"hello.cpp"] and the [^"Jamfile"] is situated.
Finally:
bjam -sTOOLS=vc-7_1
bjam -sTOOLS=msvc
We are again assuming that we are using Microsoft Visual C++ version 7.1. 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
[@../../../../../../tools/build/index.html Building Boost Libraries] for
further details.
@@ -217,26 +195,26 @@ further details.
It should be building now:
[pre
cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
]
And so on... Finally:
[pre
Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
hello.cpp
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
...updated 31 targets...
vc-C++ ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.obj
hello.cpp
vc-Link ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.pyd ..\..\..\..\libs\python\example\tutorial\bin\
hello.pyd\msvc\debug\runtime-link-dynamic\hello.lib
Creating library ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\
msvc\debug\runtime-link-dynamic\hello.lib and object ..\..\..\..\libs\python\
example\tutorial\bin\hello.pyd\msvc\debug\runtime-link-dynamic\hello.exp
...updated 40 targets...
]
If all is well, you should now have:
@@ -251,21 +229,19 @@ if you are on Windows, and
if you are on Unix.
[^boost_python.dll] and [^hello.pyd] can be found somewhere in your project's
[^bin] directory. After a successful build, you can just link in these DLLs with
the Python interpreter. In Windows for example, you can simply put these libraries
inside the directory where the Python executable is.
[^boost_python.dll] can be found somewhere in [^libs\python\build\bin]
while [^hello.pyd] can be found somewhere in
[^libs\python\example\tutorial\bin]. After a successful build, you can just
link in these DLLs with the Python interpreter. In Windows for example, you
can simply put these libraries inside the directory where the Python
executable is.
You may now fire up Python and run our hello module:
[python]
>>> import hello
>>> print hello.greet()
hello, world
[c++]
[:[*There you go... Have fun!]]
[endsect]
@@ -300,8 +276,6 @@ Here, we wrote a C++ class wrapper that exposes the member functions
[^greet] and [^set]. Now, after building our module as a shared library, we
may use our class [^World] in Python. Here's a sample Python session:
[python]
>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
@@ -320,8 +294,6 @@ which is why we were able to write
We may wish to wrap a class with a non-default constructor. Let us
build on our previous example:
[c++]
struct World
{
World(std::string msg): msg(msg) {} // added constructor
@@ -392,8 +364,6 @@ Our C++ [^Var] class and its data members can be exposed to Python:
Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:
[python]
>>> x = hello.Var('pi')
>>> x.value = 3.14
>>> print x.name, 'is around', x.value
@@ -402,10 +372,12 @@ hello as we did before:
Note that [^name] is exposed as [*read-only] while [^value] is exposed
as [*read-write].
[pre
>>> x.name = 'e' # can't change name
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
]
[endsect]
[section Class Properties]
@@ -416,8 +388,6 @@ the class' data members. The only way to access the class' data is
through access (getter/setter) functions. Access functions expose class
properties. Here's an example:
[c++]
struct Num
{
Num();
@@ -437,8 +407,6 @@ attributes can just be a different syntax for a method call. Wrapping our
And at last, in Python:
[python]
>>> x = Num()
>>> x.value = 3.14
>>> x.value, x.rovalue
@@ -448,8 +416,6 @@ And at last, in Python:
Take note that the class property [^rovalue] is exposed as [*read-only]
since the [^rovalue] setter member function is not passed in:
[c++]
.add_property("rovalue", &Num::get)
[endsect]
@@ -547,7 +513,7 @@ 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.
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
[blurb __alert__ MSVC6/7 Workaround\n\n
If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:\n\n
`return call<int>(this->get_override("f").ptr());`.]
@@ -572,7 +538,7 @@ correspond roughly to C++'s [*member functions]]
[section Virtual Functions with Default Implementations]
We've seen in the previous section how classes with pure virtual functions are
wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper]
wrapped using Boost.Python's [@../../../v2//wrapper.html class wrapper]
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
mechanism is a bit different.
@@ -611,7 +577,7 @@ We wrap it this way:
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
override for `f`. If none, then we call `Base::f()`.
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
[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());`.]
@@ -629,8 +595,6 @@ special [^def] function for this purpose.
In Python, the results would be as expected:
[python]
>>> base = Base()
>>> class Derived(Base):
... def f(self):
@@ -660,8 +624,6 @@ this and makes it easy to wrap C++ operator-powered classes.
Consider a file position class [^FilePos] and a set of operators that take
on FilePos instances:
[c++]
class FilePos { /*...*/ };
FilePos operator+(FilePos, int);
@@ -699,13 +661,13 @@ similar set of intuitive interfaces can also be used to wrap C++ functions
that correspond to these Python ['special functions]. Example:
class Rational
{ public: operator double() const; };
{ operator double() const; };
Rational pow(Rational, Rational);
Rational abs(Rational);
ostream& operator<<(ostream&,Rational);
class_<Rational>("Rational")
class_<Rational>()
.def(float_(self)) // __float__
.def(pow(self, other<Rational>)) // __pow__
.def(abs(self)) // __abs__
@@ -714,9 +676,9 @@ that correspond to these Python ['special functions]. Example:
Need we say more?
[blurb __note__ What is the business of `operator<<`?
Well, the method `str` requires the `operator<<` to do its work (i.e.
`operator<<` is used by the method defined by `def(str(self))`.]
[blurb __note__ What is the business of [^operator<<] [^.def(str(self))]?
Well, the method [^str] requires the [^operator<<] to do its work (i.e.
[^operator<<] is used by the method defined by def(str(self)).]
[endsect]
[endsect] [/ Exposing Classes ]
@@ -736,27 +698,27 @@ But before you do, you might want to fire up Python 2.2 or later and type
[^>>> import this].
[pre
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
]
[section Call Policies]
@@ -809,8 +771,6 @@ Here's what's happening:
We could copy result into a new object:
[python]
>>> f(y, z).set(42) # Result disappears
>>> y.x.get() # No crash, but still bad
3.14
@@ -821,8 +781,6 @@ closely as possible.
Our problems do not end there. Suppose Y is implemented as follows:
[c++]
struct Y
{
X x; Z* z;
@@ -1159,8 +1117,6 @@ Class [^object] wraps [^PyObject*]. All the intricacies of dealing with
To illustrate, this Python code snippet:
[python]
def f(x, y):
if (y == 'foo'):
x[3:7] = 'bar'
@@ -1173,8 +1129,6 @@ To illustrate, this Python code snippet:
Can be rewritten in C++ using Boost.Python facilities this way:
[c++]
object f(object x, object y) {
if (y == "foo")
x.slice(3,7) = "bar";
@@ -1240,22 +1194,18 @@ member functions.
Demonstrates that you can write the C++ equivalent of [^"format" % x,y,z]
in Python, which is useful since there's no easy way to do that in std C++.
[blurb
__alert__ [*Beware] the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.
]
__alert__ [*Beware] the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.
Python:
[python]
>>> d = dict(x.__dict__) # copies x.__dict__
>>> d['whatever'] # modifies the copy
C++:
[c++]
dict d(x.attr("__dict__")); // copies x.__dict__
d['whatever'] = 3; // modifies the copy
dict d(x.attr("__dict__")); # copies x.__dict__
d['whatever'] = 3; # modifies the copy
[h2 class_<T> as objects]
@@ -1289,15 +1239,16 @@ we wanted to do above can be achieved by writing:
Vec2& v = extract<Vec2&>(o);
assert(l == v.length());
The first line attempts to extract the "length" attribute of the Boost.Python
[^object]. The second line attempts to ['extract] the [^Vec2] object from held
by the Boost.Python [^object].
The first line attempts to extract the "length" attribute of the
Boost.Python [^object] [^o]. The second line attempts to ['extract] the
[^Vec2] object from held by the Boost.Python [^object] [^o].
Take note that we said "attempt to" above. What if the Boost.Python [^object]
does not really hold a [^Vec2] type? This is certainly a possibility considering
the dynamic nature of Python [^object]s. To be on the safe side, if the C++ type
can't be extracted, an appropriate exception is thrown. To avoid an exception,
we need to test for extractibility:
Take note that we said "attempt to" above. What if the Boost.Python
[^object] [^o] does not really hold a [^Vec2] type? This is certainly
a possibility considering the dynamic nature of Python [^object]s. To
be on the safe side, if the C++ type can't be extracted, an
appropriate exception is thrown. To avoid an exception, we need to
test for extractibility:
extract<Vec2&> x(o);
if (x.check()) {
@@ -1341,16 +1292,12 @@ attributes. Details can be found [@../../../v2/scope.html here].]
You can access those values in Python as
[python]
>>> my_module.choice.red
my_module.choice.red
where my_module is the module where the enum is declared. You can also
create a new scope around a class:
[c++]
scope in_X = class_<X>("X")
.def( ... )
.def( ... )
@@ -1415,20 +1362,20 @@ include path.
In a Jamfile, all the above boils down to:
[pre
projectroot c:\projects\embedded_program ; # location of the program
projectroot c:\projects\embedded_program ; # location of the program
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
<find-library>boost_python <library-path>c:\boost\libs\python
$(PYTHON_PROPERTIES)
<library-path>$(PYTHON_LIB_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
<find-library>boost_python <library-path>c:\boost\libs\python
$(PYTHON_PROPERTIES)
<library-path>$(PYTHON_LIB_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
]
[h2 Getting started]
@@ -1550,19 +1497,17 @@ the object's [^ptr] member function to retrieve the [^PyObject*].
This should create a file called 'hello.txt' in the current directory
containing a phrase that is well-known in programming circles.
[blurb
__note__ [*Note] that we wrap the return value of PyRun_String in a
(nameless) [^handle] even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
]
__note__ [*Note] that we wrap the return value of PyRun_String in a
(nameless) [^handle] even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
[h2 Beyond handles]
It's nice that [^handle] 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
class to manipulate Python objects. But we have already seen such a class
above, and in the [@python/object.html previous section]: the aptly
above, and in the [@object.html previous section]: the aptly
named [^object] class and it's derivatives. We've already seen that they
can be constructed from a [^handle]. The following examples should further
illustrate this fact:
@@ -1597,12 +1542,10 @@ PyRun_String return the result directly with Py_eval_input:
int five_squared = extract<int>(result);
[blurb
__note__ [*Note] that [^object]'s member function to return the wrapped
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
take into account the different functions that [^object] and [^handle]
perform.
]
__note__ [*Note] that [^object]'s member function to return the wrapped
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
take into account the different functions that [^object] and [^handle]
perform.
[h2 Exception handling]
@@ -1691,8 +1634,6 @@ iterators, but these are two very different beasts.
The typical Python iteration protocol: [^[*for y in x...]] is as follows:
[python]
iter = x.__iter__() # get iterator
try:
while 1:
@@ -1702,11 +1643,9 @@ The typical Python iteration protocol: [^[*for y in x...]] is as follows:
Boost.Python provides some mechanisms to make C++ iterators play along
nicely as Python iterators. What we need to do is to produce
appropriate `__iter__` function from C++ iterators that is compatible
appropriate __iter__ function from C++ iterators that is compatible
with the Python iteration protocol. For example:
[c++]
object get_iterator = iterator<vector<int> >();
object iter = get_iterator(v);
object first = iter.next();
@@ -1738,8 +1677,6 @@ with &T::begin, &T::end.
Let's put this into action... Here's an example from some hypothetical
bogon Particle accelerator code:
[python]
f = Field()
for x in f.pions:
smash(x)
@@ -1748,8 +1685,6 @@ bogon Particle accelerator code:
Now, our C++ Wrapper:
[c++]
class_<F>("Field")
.property("pions", range(&F::p_begin, &F::p_end))
.property("bogons", range(&F::b_begin, &F::b_end));
@@ -1839,14 +1774,14 @@ Unix and [^.dll] for Windows, works just as well.]
Now, we create this directory structure for our Python package:
[pre
sounds/
\_\_init\_\_.py
core.pyd
filters.pyd
io.pyd
sounds/
__init__.py
core.pyd
filters.pyd
io.pyd
]
The file [^\_\_init\_\_.py] is what tells Python that the directory [^sounds/] is
The file [^__init__.py] is what tells Python that the directory [^sounds/] is
actually a Python package. It can be a empty file, but can also perform some
magic, that will be shown later.
@@ -1854,8 +1789,6 @@ Now our package is ready. All the user has to do is put [^sounds] into his
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH]
and fire up the interpreter:
[python]
>>> import sounds.io
>>> import sounds.filters
>>> sound = sounds.io.open('file.mp3')
@@ -1873,8 +1806,6 @@ it.
If we want this flexibility, we will have to complicate our package hierarchy a
little. First, we will have to change the name of the extension modules:
[c++]
/* file core.cpp */
BOOST_PYTHON_MODULE(_core)
{
@@ -1887,32 +1818,30 @@ be changed to [^_core.pyd] as well, and we do the same to the other extension mo
Now, we change our package hierarchy like so:
[pre
sounds/
\_\_init\_\_.py
core/
\_\_init\_\_.py
_core.pyd
filters/
\_\_init\_\_.py
_filters.pyd
io/
\_\_init\_\_.py
_io.pyd
sounds/
__init__.py
core/
__init__.py
_core.pyd
filters/
__init__.py
_filters.pyd
io/
__init__.py
_io.pyd
]
Note that we created a directory for each extension module, and added a
\_\_init\_\_.py to each one. But if we leave it that way, the user will have to
__init__.py to each one. But if we leave it that way, the user will have to
access the functions in the core module with this syntax:
[python]
>>> import sounds.core._core
>>> sounds.core._core.foo(...)
which is not what we want. But here enters the [^\_\_init\_\_.py] magic: everything
that is brought to the [^\_\_init\_\_.py] namespace can be accessed directly by the
which is not what we want. But here enters the [^__init__.py] magic: everything
that is brought to the [^__init__.py] namespace can be accessed directly by the
user. So, all we have to do is bring the entire namespace from [^_core.pyd]
to [^core/\_\_init\_\_.py]. So add this line of code to [^sounds/core/\_\_init\_\_.py]:
to [^core/__init__.py]. So add this line of code to [^sounds/core/__init__.py]:
from _core import *
@@ -1935,7 +1864,7 @@ create a file named [^sounds/filters/echo_noise.py] and code our function:
s = _filters.noise(sound)
return s
Next, we add this line to [^sounds/filters/\_\_init\_\_.py]:
Next, we add this line to [^sounds/filters/__init__.py]:
from echo_noise import echo_noise
@@ -1970,8 +1899,6 @@ Yes, Python rox. :-)
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class [^point] in C++:
[c++]
class point {...};
BOOST_PYTHON_MODULE(_geom)
@@ -1981,9 +1908,7 @@ we have a class [^point] in C++:
If we are using the technique from the previous session,
[link python.creating_packages Creating Packages], we can code directly
into [^geom/\_\_init\_\_.py]:
[python]
into [^geom/__init__.py]:
from _geom import *
@@ -2052,8 +1977,6 @@ time to compile the Boost.Python wrappers. Plus the memory consumption can
easily become too high. If this is causing you problems, you can split the
class_ definitions in multiple files:
[c++]
/* file point.cpp */
#include <point.h>
#include <boost/python.hpp>

File diff suppressed because it is too large Load Diff

32
doc/v2/bibliography.html Normal file
View File

@@ -0,0 +1,32 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Bibliography</title>
</head>
<body link="#0000ff" vlink="#800080">
<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>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Bibliography</h2>
</td>
</tr>
</table>
<hr>
{{bibliographical information}}
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -79,7 +79,7 @@ call_method&lt;ResultType&gt;(self_object, "<i>method-name</i>", a1, a2... a<i>N
the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into
new Python objects, but this behavior can be overridden by the use of
<code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href=
"../../../bind/ref.html">ref()</a>:</p>
"../../../bind/ref.html#reference_wrapper">ref()</a>:</p>
<pre>
class X : boost::noncopyable
{
@@ -128,7 +128,7 @@ void apply(PyObject* callable, X&amp; x)
<tr>
<td><code><a href=
"../../../bind/ref.html">boost::reference_wrapper</a>&lt;T&gt;</code></td>
"../../../bind/ref.html#reference_wrapper">boost::reference_wrapper</a>&lt;T&gt;</code></td>
<td>The Python argument contains a pointer to, rather than a copy of,
<code>x.get()</code>. Note: failure to ensure that no Python code

File diff suppressed because it is too large Load Diff

View File

@@ -126,7 +126,7 @@ void handle_exception() throw();
<dt><b>Rationale:</b> At inter-language boundaries it is important to
ensure that no C++ exceptions escape, since the calling language
usually doesn't have the equipment necessary to properly unwind the
usually doesn't have the equipment neccessary to properly unwind the
stack. Use <code>handle_exception</code> to manage exception
translation whenever your C++ code is called directly from the Python
API. This is done for you automatically by the usual function wrapping
@@ -134,7 +134,7 @@ void handle_exception() throw();
"make_function.html#make_function-spec">make_function</a>()</code>,
<code><a href=
"make_function.html#make_constructor-spec">make_constructor</a>()</code>,
<code><a href="def.html#class_-spec-modifiers">def</a>()</code> and <code><a href=
<code><a href="def.html#def-spec">def</a>()</code> and <code><a href=
"class.html#def-spec">class_::def</a>()</code>. The second form can be
more convenient to use (see the <a href="#examples">example</a> below),
but various compilers have problems when exceptions are rethrown from

165
doc/v2/from_python.html Normal file
View File

@@ -0,0 +1,165 @@
<!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=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/from_python.hpp&gt;</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 &lt;boost/python/from_python.hpp&gt;</h2>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a>
<dt><a href="#classes">Classes</a>
<dd>
<dl class="page-index">
<dt><a href="#from_python-spec">Class
Template<code>from_python</code></a>
<dd>
<dl class="page-index">
<dt><a href="#from_python-spec-synopsis">Class Template
<code>from_python</code> synopsis</a>
<dt><a href="#from_python-spec-ctors">Class Template
<code>from_python</code> constructor</a>
<dt><a href="#from_python-spec-observers">Class Template
<code>from_python</code> observer functions</a>
</dl>
</dl>
<dt><a href="#examples">Example</a>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code>&lt;boost/python/from_python.hpp&gt;</code> introduces a class
template <code>from_python&lt;T&gt;</code> for extracting a C++ object of
type <code>T</code> from a Python object.
<h2><a name="classes"></a>Classes</h2>
<h3><a name="from_python-spec"></a>Class Template
<code>from_python&lt;class T&gt;</code></h3>
<p><code>from_python&lt;T&gt;</code> is the type used internally by
Boost.Python to extract C++ function arguments from a Python argument tuple
when calling a wrapped function. It can also be used directly to make
similar conversions in other contexts.
<h4><a name="from_python-spec-synopsis"></a>Class Template
<code>from_python</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
template &lt;class T&gt;
struct from_python : private <a href=
"../../../utility/utility.htm#Class_noncopyable">boost::noncopyable</a> // Exposition only.
// from_python&lt;T&gt; meets the NonCopyable requirements
{
from_python(PyObject*);
bool convertible() const;
<i>convertible-to-T</i> operator()(PyObject*) const;
};
}
</pre>
<h4><a name="from_python-spec-ctors"></a>Class Template
<code>from_python</code> constructor</h4>
<pre>
from_python(PyObject* p);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>p != 0</code>
<dt><b>Effects:</b> Constructs a <code>from_python</code> object suitable
for extracting a C++ object of type <code>T</code> from <code>p</code>.
</dl>
<h4><a name="from_python-spec-observers"></a>Class Template
<code>from_python</code> observer functions</h4>
<pre>
bool convertible() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> <code>false</code> if the conversion cannot succeed.
This indicates that either:
<dd>
<ol>
<li>No <code>from_python_converter</code> was registered for
<code>T</code>, or
<li>any such converter rejected the constructor argument
<code>p</code> by returning <code>0</code> from its
<code>convertible()</code> function
</ol>
Note that conversion may still fail in <code>operator()</code> due to
an exception.
<dt><b>Throws:</b> nothing
<dt><b>Rationale:</b> Because <code>from_python&lt;&gt;</code> is used in
overload resolution, and throwing an exception can be slow, it is useful
to be able to rule out a broad class of unsuccessful conversions without
throwing an exception.
</dl>
<pre>
<i>convertible-to-T</i> operator()(PyObject* p) const;
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>*p</code> refers to the same object which was
passed to the constructor, and <code>convertible()</code> returns
<code>true</code>.
<dt><b>Effects:</b> performs the conversion
<dt><b>Returns:</b> an object convertible to <code>T</code>.
</dl>
<h2><a name="examples"></a>Example</h2>
<pre>
#include &lt;string&gt;
#include &lt;boost/python/from_python.hpp&gt;
// If a std::string can be extracted from p, return its
// length. Otherwise, return 0.
std::size_t length_if_string(PyObject* p)
{
from_python&lt;std::string&gt; converter(p);
if (!converter.convertible())
return 0;
else
return converter(p).size();
}
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002. </i>

288
doc/v2/header.html Normal file
View File

@@ -0,0 +1,288 @@
<!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=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;{{header}}&gt;</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 &lt;{{header}}&gt;</h2>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a>
<dt><a href="#macros">Macros</a>
<dd>
<dl class="page-index">
<dt><a href="#macro-spec">{{macro name}}</a>
</dl>
<dt><a href="#values">Values</a>
<dd>
<dl class="page-index">
<dt><a href="#value-spec">{{value name}}</a>
</dl>
<dt><a href="#types">Types</a>
<dd>
<dl class="page-index">
<dt><a href="#type-spec">{{type name}}</a>
</dl>
<dt><a href="#classes">Classes</a>
<dd>
<dl class="page-index">
<dt><a href="#class-spec">Class <code>{{name}}</code></a>
<dd>
<dl class="page-index">
<dt><a href="#class-spec-synopsis">Class <code>{{name}}</code> synopsis</a>
<dt><a href="#class-spec-ctors">Class <code>{{name}}</code>
constructors and destructor</a>
<dt><a href="#class-spec-comparisons">Class <code>{{name}}</code> comparison functions</a>
<dt><a href="#class-spec-modifiers">Class <code>{{name}}</code> modifier functions</a>
<dt><a href="#class-spec-observers">Class <code>{{name}}</code> observer functions</a>
<dt><a href="#class-spec-statics">Class <code>{{name}}</code> static functions</a>
</dl>
</dl>
<dt><a href="#functions">Functions</a>
<dd>
<dl class="page-index">
<dt><a href="#function-spec">{{function name}}</a>
</dl>
<dt><a href="#objects">Objects</a>
<dd>
<dl class="page-index">
<dt><a href="#object-spec">{{object name}}</a>
</dl>
<dt><a href="#examples">Example(s)</a>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>{{Introductory text}}
<h2><a name="macros"></a>Macros</h2>
<p><a name="macro-spec"></a>{{Macro specifications}}
<h2><a name="values"></a>Values</h2>
<p><a name="value-spec"></a>{{Value specifications}}
<h2><a name="types"></a>Types</h2>
<p><a name="type-spec"></a>{{Type specifications}}
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-spec"></a>Class <code>{{name}}</code></h3>
<p>{{class overview text}}
<h4><a name="class-spec-synopsis"></a>Class <code>{{name}}</code> synopsis</h4>
<pre>
namespace boost
{
class {{name}}
{
};
};
</pre>
<h4><a name="class-spec-ctors"></a>Class <code>{{name}}</code> constructors and
destructor</h4>
<pre>
{{constructor}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<pre>
{{destructor}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h4><a name="class-spec-comparisons"></a>Class <code>{{name}}</code> comparison
functions</h4>
<pre>
{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h4><a name="class-spec-modifiers"></a>Class <code>{{name}}</code> modifier
functions</h4>
<pre>
{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h4><a name="class-spec-observers"></a>Class <code>{{name}}</code> observer
functions</h4>
<pre>
{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h4><a name="class-spec-statics"></a>Class <code>{{name}}</code> static functions</h4>
<pre>
{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="function-spec"></a>{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}
<dt><b>Effects:</b> {{text}}
<dt><b>Postconditions:</b> {{text}}
<dt><b>Returns:</b> {{text}}
<dt><b>Throws:</b> {{text}}
<dt><b>Complexity:</b> {{text}}
<dt><b>Rationale:</b> {{text}}
</dl>
<h2><a name="objects"></a>Objects</h2>
<p><a name="object-spec"></a>{{Object specifications}}
<h2><a name="examples"></a>Example(s)</h2>
<p>{{Example(s)}}
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002. </i>

View File

@@ -45,7 +45,7 @@
<dt><a href="#iterator-spec-synopsis">Class
<code>iterator</code> synopsis</a></dt>
<dt><a href="#iterator-spec-constructors">Class template
<dt><a href="#iterator-spec-ctors">Class template
<code>iterator</code> constructor</a></dt>
</dl>
</dd>

View File

@@ -71,7 +71,7 @@ This macro generates two functions in the scope where it is used:
and <code>void&nbsp;init_module_<i>name</i>()</code>, whose body must
follow the macro invocation. <code>init_<i>name</i></code> passes
<code>init_module_<i>name</i></code> to <code><a
href="errors.html#handle_exception-spec">handle_exception</a>()</code> so
href="errors.html#handle_exception">handle_exception</a>()</code> so
that any C++ exceptions generated are safely processeed. During the
body of <code>init_<i>name</i></code>, the current <code><a
href="scope.html#scope-spec">scope</a></code> refers to the module

View File

@@ -186,7 +186,7 @@
</dl>
<dl class="page-index">
<dt><a href="#object_operators-spec">operators</a></dt>
<dt><a href="#operators-spec">operators</a></dt>
</dl>
</dd>
@@ -232,7 +232,7 @@ x[slice(_,_,-1)]
<p>The policies which are used for proxies representing an attribute
access to a <code>const&nbsp;object</code>.</p>
<h4><a name="const_attribute_policies-spec-synopsis"></a>Class
<h4><a name="class-spec-synopsis"></a>Class
<code>const_attribute_policies</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace api

View File

@@ -123,7 +123,7 @@ explicit opaque_pointer_converter(char const* name);
<h2><a name="examples"></a>Example</h2>
please see example for <a href="return_opaque_pointer.html#examples">
please see example for <a href="return_opaque_pointer.html#example">
return_opaque_pointer</a>.
<h2><a name="see-also"></a>See Also</h2>

View File

@@ -57,7 +57,7 @@
<dt><a href="#self_t-spec-value-unary-ops">Class
<code>self_t</code> unary operations</a></dt>
<dt><a href="#self_t-spec-value-ops">Class
<dt><a href="#self_t-spec-value-value-ops">Class
<code>self_t</code> value operations</a></dt>
</dl>
</dd>

48
doc/v2/overview.html Normal file
View File

@@ -0,0 +1,48 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Overview</title>
</head>
<body link="#0000ff" vlink="#800080">
<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>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Overview</h2>
</td>
</tr>
</table>
<hr>
<dl class="index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#topic1">First topic</a></dt>
<dt><a href="#topic2">Second topic</a></dt>
<dt><a href="#footnotes">Footnotes</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>{{text}}</p>
<h2><a name="topic1"></a>First Topic</h2>
<p>{{text}}</p>
<h2><a name="topic2"></a>Second Topic</h2>
<p>{{text}}</p>
<h2><a name="footnotes"></a>Footnotes</h2>
<dl>
<dt><a name="footnote1" class="footnote">(1)</a> {{text}}</dt>
<dt><a name="footnote2" class="footnote">(2)</a> {{text}}</dt>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -51,11 +51,13 @@
3.1, and 3.2 on <a href="http://www.redhat.com">RedHat Linux 7.3</a>
for Intel x86</dt>
<dt>Tru64 CXX 6.5.1 on OSF v. 5.1 for Dec/Compaq
Alpha</dt>
<dt><a href=
"http://www.tru64unix.compaq.com/cplus/index.html">Tru64 CXX
6.5.1</a> on OSF v. 5.1 for Dec/Compaq Alpha</dt>
<dt>
MIPSPro 7.3.1.2m on <a href=
<dt><a href=
"http://www.sgi.com/developers/devtools/languages/mipspro.html">
MIPSPro 7.3.1.2m</a> on <a href=
"http://www.sgi.com/software/irix6.5/">IRIX 6.5</a> for SGI
mips</dt>
@@ -68,16 +70,21 @@
<dd>
<dl>
<dt>KCC 3.4d on OSF v. 5.1 for Dec/Compaq Alpha</dt>
<dt><a href=
"http://developer.intel.com/software/products/kcc/">KCC
3.4d</a> on OSF v. 5.1 for Dec/Compaq Alpha</dt>
<dt>KCC 3.4d</a> on AIX</dt>
<dt><a href=
"http://developer.intel.com/software/products/kcc/">KCC
3.4d</a> on AIX</dt>
</dl>
</dd>
</dl>
<br>
</dd>
<dt>Microsoft Windows XP Professional with Python <a href=
<dt><a href="http://www.microsoft.com/windowsxp/default.asp">Microsoft
Windows XP Professional</a> with Python <a href=
"http://www.python.org/2.2">2.2</a>, <a href=
"http://www.python.org/2.2.1">2.2.1</a>, and <a href=
"http://www.python.org/2.2.2">2.2.2b1</a>:</dt>

View File

@@ -45,8 +45,8 @@
<p><code>&lt;boost/python/pointee.hpp&gt;</code> introduces a
traits <a
href="../../../mpl/doc/refmanual/metafunction.html">metafunction</a>
template <code>pointee&lt;T&gt;</code> that can be used to extract the &quot;pointed-to&quot; type from the type of a pointer or smart pointer.
href="../../../mpl/doc/index.html#metafunctions">metafunction</a>
template <code>pointee&lt;T&gt;</code> which can be used to extract the &quot;pointed-to&quot; type from the type of a pointer or smart pointer.
<h2><a name="classes"></a>Classes</h2>

48
doc/v2/rationale.html Normal file
View File

@@ -0,0 +1,48 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - Rationale</title>
</head>
<body link="#0000ff" vlink="#800080">
<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>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Rationale</h2>
</td>
</tr>
</table>
<hr>
<dl class="index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#topic1">First topic</a></dt>
<dt><a href="#topic2">Second topic</a></dt>
<dt><a href="#footnotes">Footnotes</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>{{text}}</p>
<h2><a name="topic1"></a>First Topic</h2>
<p>{{text}}</p>
<h2><a name="topic2"></a>Second Topic</h2>
<p>{{text}}</p>
<h2><a name="footnotes"></a>Footnotes</h2>
<dl>
<dt><a name="footnote1" class="footnote">(1)</a> {{text}}</dt>
<dt><a name="footnote2" class="footnote">(2)</a> {{text}}</dt>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
2002. </i></p>
</body>
</html>

View File

@@ -76,7 +76,7 @@
<dt><a href=
"Dereferenceable.html#Dereferenceable-concept">Dereferenceable</a></dt>
<dt><a href="Extractor.html#Extractor-concept">Extractor</a></dt>
<dt><a href="Dereferenceable.html#Extractor-concept">Extractor</a></dt>
<dt><a href=
"HolderGenerator.html#HolderGenerator-concept">HolderGenerator</a></dt>
@@ -981,7 +981,7 @@
<dd>
<dl class="index">
<dt>class template <a href=
"pointee.html#pointee-spec">pointee</a></dt>
"pointee.html#pointee">pointee</a></dt>
</dl>
</dd>
</dl>

View File

@@ -102,9 +102,9 @@ template &lt;class T&gt; struct apply
<dt><b>Returns:</b> <code>typedef <a href=
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a>&lt;T,V&gt;
type</code>, where <code>V</code> is a class whose
static <code>execute</code> function constructs an instance
holder containing an <i>unowned</i>
type</code>, where <code>V</code> is a <a href=
"to_python_indirect.html#HolderObjectGenerator">HolderObjectGenerator</a>
which constructs an instance holder containing an <i>unowned</i>
<code>U*</code> pointing to the referent of the wrapped function's
return value.</dt>
</dl>

View File

@@ -137,8 +137,8 @@ namespace boost { namespace python
}}
</pre>
<h4><a name="return_internal_reference-spec-statics"></a>Class
<code>return_internal_reference</code> static functions</h4>
<h4><a name="default_call_policies-spec-statics"></a>Class
<code>default_call_policies</code> static functions</h4>
<pre>
PyObject* postcall(PyObject* args, PyObject* result);
</pre>

View File

@@ -53,7 +53,7 @@ for the Python <a
href="http://www.python.org/doc/2.3.3/api/slice-objects.html">slice</a>
type.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="slice-spec"></a>Class <code>slice</code></h3>
<h3><a name="class-spec"></a>Class <code>slice</code></h3>
<p>Exposes the extended slicing protocol by wrapping the built-in slice
type. The semantics of the constructors and member functions defined
below can be fully understood by reading the <a
@@ -134,7 +134,7 @@ slice(Int1 start, Int2 stop, Int3 step);
<dt><b>Effects:</b> constructs a new slice with start stop and step
values.&nbsp; Equivalent to the slice object created
by the built-in Python function <code><a
href="http://www.python.org/doc/current/lib/built-in-funcs.html">slice(start,stop,step)</a></code>,
href="http://www.python.org/doc/current/lib/built-in-functions.html#12h-62">slice(start,stop,step)</a></code>,
or as part of the Python expression <code>base[start:stop:step]</code>.</dt>
<dt><b>Throws:</b> <code>error_already_set</code> and sets a Python <code>TypeError</code>
exception if no conversion is possible from the arguments to type

View File

@@ -121,7 +121,7 @@ type_info(std::type_info const&amp; = typeid(void));
<dt><b>Effects:</b> constructs a <code>type_info</code> object which
identifies the same type as its argument.</dt>
<dt><b>Rationale:</b> Since it is occasionally necessary to make an
<dt><b>Rationale:</b> Since it is occasionally neccessary to make an
array of <code>type_info</code> objects a benign default argument is
supplied. <span class="c3"><b>Note:</b></span> this constructor does
<i>not</i> correct for non-conformance of compiler

View File

@@ -60,22 +60,4 @@ boost-python-runtest test2
: # Python test driver
test_getting_started2.py
# extension modules to use
<pyd>getting_started2 ;
# ----- std_pair -------
# Declare a Python extension called std_pair
extension std_pair_ext
: # sources
std_pair.cpp
# requirements and dependencies for Boost.Python extensions
<template>@boost/libs/python/build/extension
;
# Declare a test for the extension module
boost-python-runtest test3
: # Python test driver
test_std_pair.py
# extension modules to use
<pyd>std_pair_ext ;
<pyd>getting_started2 ;

View File

@@ -1,9 +1,12 @@
# This is the Jamfile for Boost.Build v2, which is currently in
# prerelease. Ignore this file unless you are a bleading edge sort of
# person.
use-project /boost/python : ../build ;
project : requirements <library>/boost/python//boost_python ;
python-extension getting_started1 : getting_started1.cpp ;
python-extension getting_started2 : getting_started2.cpp ;
project
: requirements <library>/boost/python//boost_python
;
python-extension getting_started1 : getting_started1.cpp : <link>shared ;
python-extension getting_started2 : getting_started2.cpp : <link>shared ;

View File

@@ -2,8 +2,6 @@
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <string>
namespace { // Avoid cluttering the global namespace.
@@ -13,6 +11,8 @@ namespace { // Avoid cluttering the global namespace.
int square(int number) { return number * number; }
}
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every

View File

@@ -2,9 +2,6 @@
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <iostream>
#include <string>
@@ -26,6 +23,10 @@ namespace { // Avoid cluttering the global namespace.
}
}
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
BOOST_PYTHON_MODULE(getting_started2)
{
using namespace boost::python;

View File

@@ -1,46 +0,0 @@
// Copyright Ralf W. Grosse-Kunstleve 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)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
namespace { // Avoid cluttering the global namespace.
// Converts a std::pair instance to a Python tuple.
template <typename T1, typename T2>
struct std_pair_to_tuple
{
static PyObject* convert(std::pair<T1, T2> const& p)
{
return boost::python::incref(
boost::python::make_tuple(p.first, p.second).ptr());
}
};
// Helper for convenience.
template <typename T1, typename T2>
struct std_pair_to_python_converter
{
std_pair_to_python_converter()
{
boost::python::to_python_converter<
std::pair<T1, T2>,
std_pair_to_tuple<T1, T2> >();
}
};
// Example function returning a std::pair.
std::pair<int, int>
foo() { return std::pair<int, int>(3, 5); }
} // namespace anonymous
BOOST_PYTHON_MODULE(std_pair_ext)
{
using namespace boost::python;
std_pair_to_python_converter<int, int>();
def("foo", foo);
}

View File

@@ -1,3 +0,0 @@
import std_pair_ext
assert std_pair_ext.foo() == (3, 5)
print "OK"

View File

@@ -1,18 +1,14 @@
# Hello World Example from the tutorial
# 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)
# [Joel de Guzman 10/9/2002]
# This is the top of our own project tree
project-root ;
# Specify our location in the boost project hierarchy
subproject libs/python/example/tutorial ;
# Include definitions needed for Python modules
import python ;
extension hello # Declare a Python extension called hello
: hello.cpp # source
# requirements and dependencies for Boost.Python extensions
<template>@boost/libs/python/build/extension
<dll>../../build/boost_python # dependencies
;

View File

@@ -1,36 +0,0 @@
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
# and conditions of use.
# If you move this example from its place in the Boost tree, edit this
# path to point at the root directory of your Boost installation (the
# one containing a subdirectory called "boost/" and a sub-subdirectory
# "boost/python/" full of .hpp files). Absolute paths work, too.
#
path-global BOOST_ROOT : ../../../.. ;
# Boost.Python configuration variables, as described in
# http://www.boost.org/libs/python/doc/building.html#configuration.
# Usually you don't need to set these; the defaults will work. If you
# do set them, try to change as few of them as possible, starting with
# the first ones.
# PYTHON_VERSION = <the two-part Major.Minor version number, e.g. 2.2> ;
# PYTHON_ROOT = <root directory of your Python installation, e.g. /usr> ;
# PYTHON_INCLUDES = <path to Python #include directories> ;
# PYTHON_LIB_PATH = <path to Python library object> ;
# You may need to configure your compiler toolset, especially if you
# want to build with a compiler that is not the "system default" or if
# it is installed in a nonstandard place; see
# http://www.boost.org/more/getting_started.html#Configuring for
# details.
# Makes a project id for boost so that other Boost.Build projects can
# refer to it by name.
#
project boost : $(BOOST_ROOT) ;
# Change this setting to have all your built products placed under a
# single directory:
#
# ALL_LOCATE_TARGET = <root directory for all built products>

View File

@@ -35,7 +35,6 @@
# include <boost/python/list.hpp>
# include <boost/python/long.hpp>
# include <boost/python/lvalue_from_pytype.hpp>
# include <boost/python/make_constructor.hpp>
# include <boost/python/make_function.hpp>
# include <boost/python/manage_new_object.hpp>
# include <boost/python/module.hpp>

View File

@@ -277,86 +277,43 @@ class class_ : public objects::class_base
// Data member access
//
template <class D>
self& def_readonly(char const* name, D const& d, char const* doc=0)
self& def_readonly(char const* name, D const& d)
{
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D const& d, char const* doc=0)
self& def_readwrite(char const* name, D const& d)
{
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readonly(char const* name, D& d, char const* doc=0)
self& def_readonly(char const* name, D& d)
{
return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D& d, char const* doc=0)
self& def_readwrite(char const* name, D& d)
{
return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
// Property creation
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
template <class Get>
self& add_property(char const* name, Get fget, char const* docstr = 0)
{
base::add_property(name, this->make_getter(fget), docstr);
return *this;
}
template <class Get, class Set>
self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
{
base::add_property(
name, this->make_getter(fget), this->make_setter(fset), docstr);
return *this;
}
# else
private:
template <class Get>
self& add_property_impl(char const* name, Get fget, char const* docstr, int)
{
base::add_property(name, this->make_getter(fget), docstr);
return *this;
}
template <class Get, class Set>
self& add_property_impl(char const* name, Get fget, Set fset, ...)
{
base::add_property(
name, this->make_getter(fget), this->make_setter(fset), 0);
return *this;
}
public:
template <class Get>
self& add_property(char const* name, Get fget)
{
base::add_property(name, this->make_getter(fget), 0);
return *this;
}
template <class Get, class DocStrOrSet>
self& add_property(char const* name, Get fget, DocStrOrSet docstr_or_set)
{
this->add_property_impl(name, this->make_getter(fget), docstr_or_set, 0);
base::add_property(name, this->make_getter(fget));
return *this;
}
template <class Get, class Set>
self&
add_property(char const* name, Get fget, Set fset, char const* docstr)
self& add_property(char const* name, Get fget, Set fset)
{
base::add_property(
name, this->make_getter(fget), this->make_setter(fset), docstr);
base::add_property(name, this->make_getter(fget), this->make_setter(fset));
return *this;
}
# endif
template <class Get>
self& add_static_property(char const* name, Get fget)
@@ -464,28 +421,28 @@ class class_ : public objects::class_base
template <class D, class B>
self& def_readonly_impl(
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
return this->add_property(name, pm_, doc);
return this->add_property(name, pm_);
}
template <class D, class B>
self& def_readwrite_impl(
char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
return this->add_property(name, pm_, pm_, doc);
return this->add_property(name, pm_, pm_);
}
template <class D>
self& def_readonly_impl(
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, python::make_getter(d));
}
template <class D>
self& def_readwrite_impl(
char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
}

View File

@@ -11,12 +11,7 @@
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/not.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/converter/registered_pointee.hpp>
@@ -146,49 +141,61 @@ struct back_reference_arg_from_python
// ==================
template <class C, class T, class F>
struct if_2
{
typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type;
};
// This metafunction selects the appropriate arg_from_python converter
// type for an argument of type T.
template <class T>
struct select_arg_from_python
{
typedef typename if_2<
is_object_manager<T>
, object_manager_value_arg_from_python<T>
, if_2<
is_reference_to_object_manager<T>
, object_manager_ref_arg_from_python<T>
, if_2<
is_pointer<T>
, pointer_arg_from_python<T>
, if_2<
mpl::and_<
indirect_traits::is_reference_to_pointer<T>
, indirect_traits::is_reference_to_const<T>
, mpl::not_<indirect_traits::is_reference_to_volatile<T> >
>
, pointer_cref_arg_from_python<T>
, if_2<
mpl::or_<
indirect_traits::is_reference_to_non_const<T>
, indirect_traits::is_reference_to_volatile<T>
>
, reference_arg_from_python<T>
, mpl::if_<
boost::python::is_back_reference<T>
, back_reference_arg_from_python<T>
, arg_rvalue_from_python<T>
>
>
>
>
>
>::type type;
BOOST_STATIC_CONSTANT(
bool, obj_mgr = is_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, obj_mgr_ref = is_reference_to_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, ptr = is_pointer<T>::value);
BOOST_STATIC_CONSTANT(
bool, ptr_cref
= indirect_traits::is_reference_to_pointer<T>::value
&& indirect_traits::is_reference_to_const<T>::value
&& !indirect_traits::is_reference_to_volatile<T>::value);
BOOST_STATIC_CONSTANT(
bool, ref =
indirect_traits::is_reference_to_non_const<T>::value
|| indirect_traits::is_reference_to_volatile<T>::value);
BOOST_STATIC_CONSTANT(
bool, back_ref =
boost::python::is_back_reference<T>::value);
typedef typename mpl::if_c<
obj_mgr
, object_manager_value_arg_from_python<T>
, typename mpl::if_c<
obj_mgr_ref
, object_manager_ref_arg_from_python<T>
, typename mpl::if_c<
ptr
, pointer_arg_from_python<T>
, typename mpl::if_c<
ptr_cref
, pointer_cref_arg_from_python<T>
, typename mpl::if_c<
ref
, reference_arg_from_python<T>
, typename mpl::if_c<
back_ref
, back_reference_arg_from_python<T>
, arg_rvalue_from_python<T>
>::type
>::type
>::type
>::type
>::type
>::type type;
};
// ==================

View File

@@ -11,14 +11,7 @@
# include <boost/type_traits/cv_traits.hpp>
# include <boost/detail/workaround.hpp>
namespace boost {
// You'll see shared_ptr mentioned in this header because we need to
// note which types are shared_ptrs in their registrations, to
// implement special shared_ptr handling for rvalue conversions.
template <class T> class shared_ptr;
namespace python { namespace converter {
namespace boost { namespace python { namespace converter {
struct registration;
@@ -33,9 +26,9 @@ namespace detail
template <class T>
struct registered
: detail::registered_base<
: detail::registered_base<
typename add_reference<
typename add_cv<T>::type
typename add_cv<T>::type
>::type
>
{
@@ -57,37 +50,10 @@ struct registered<T&>
//
namespace detail
{
inline void
register_shared_ptr0(...)
{
}
template <class T>
inline void
register_shared_ptr0(shared_ptr<T>*)
{
registry::lookup_shared_ptr(type_id<shared_ptr<T> >());
}
template <class T>
inline void
register_shared_ptr1(T const volatile*)
{
detail::register_shared_ptr0((T*)0);
}
template <class T>
registration const&
registry_lookup(T&(*)())
{
detail::register_shared_ptr1((T*)0);
return registry::lookup(type_id<T&>());
}
template <class T>
registration const& registered_base<T>::converters = detail::registry_lookup((T(*)())0);
registration const& registered_base<T>::converters
= registry::lookup(type_id<T>());
}
}}} // namespace boost::python::converter
#endif // REGISTERED_DWA2002710_HPP

View File

@@ -33,7 +33,7 @@ struct rvalue_from_python_chain
struct BOOST_PYTHON_DECL registration
{
public: // member functions
explicit registration(type_info target, bool is_shared_ptr = false);
explicit registration(type_info);
// Convert the appropriately-typed data to Python
PyObject* to_python(void const volatile*) const;
@@ -56,11 +56,7 @@ struct BOOST_PYTHON_DECL registration
// The unique to_python converter for the associated C++ type.
to_python_function_t m_to_python;
// True iff this type is a shared_ptr. Needed for special rvalue
// from_python handling.
const bool is_shared_ptr;
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
private:
void operator=(registration); // This is not defined, and just keeps MWCW happy.
@@ -70,13 +66,12 @@ struct BOOST_PYTHON_DECL registration
//
// implementations
//
inline registration::registration(type_info target_type, bool is_shared_ptr)
inline registration::registration(type_info target_type)
: target_type(target_type)
, lvalue_chain(0)
, rvalue_chain(0)
, m_class_object(0)
, m_to_python(0)
, is_shared_ptr(is_shared_ptr)
{}
inline bool operator<(registration const& lhs, registration const& rhs)

View File

@@ -17,13 +17,9 @@ struct registration;
// This namespace acts as a sort of singleton
namespace registry
{
// Get the registration corresponding to the type, creating it if necessary
// Get the registration corresponding to the type, creating it if neccessary
BOOST_PYTHON_DECL registration const& lookup(type_info);
// Get the registration corresponding to the type, creating it if
// necessary. Use this first when the type is a shared_ptr.
BOOST_PYTHON_DECL registration const& lookup_shared_ptr(type_info);
// Return a pointer to the corresponding registration, if one exists
BOOST_PYTHON_DECL registration const* query(type_info);

View File

@@ -13,7 +13,6 @@
# define CONFIG_DWA052200_H_
# include <boost/config.hpp>
# include <boost/detail/workaround.hpp>
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
// A gcc bug forces some symbols into the global namespace
@@ -106,7 +105,7 @@
# define BOOST_PYTHON_DECL_EXCEPTION BOOST_PYTHON_DECL
#endif
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
#if (defined(__DECCXX_VER) && __DECCXX_VER <= 60590041)
// Replace broken Tru64/cxx offsetof macro
# define BOOST_PYTHON_OFFSETOF(s_name, s_member) \
((size_t)__INTADDR__(&(((s_name *)0)->s_member)))

View File

@@ -168,7 +168,7 @@ namespace detail
char const* doc)
{
// define the NTH stub function of stubs
define_stub_function<N>::define(name, stubs, kw, policies, name_space, 0);
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
if (kw.second > kw.first)
--kw.second;

View File

@@ -1,13 +1,62 @@
// Copyright David Abrahams 2005.
// Copyright David Abrahams 2003.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef IS_XXX_DWA2003224_HPP
# define IS_XXX_DWA2003224_HPP
# include <boost/detail/is_xxx.hpp>
# include <boost/config.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params.hpp>
# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
BOOST_DETAIL_IS_XXX_DEF(name, qualified_name, nargs)
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/add_reference.hpp>
# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
template <class X_> \
struct is_##name \
{ \
typedef char yes; \
typedef char (&no)[2]; \
\
static typename add_reference<X_>::type dummy; \
\
struct helpers \
{ \
template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class U) > \
static yes test( \
qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, U) >&, int \
); \
\
template <class U> \
static no test(U&, ...); \
}; \
\
BOOST_STATIC_CONSTANT( \
bool, value \
= !is_reference<X_>::value \
& (sizeof(helpers::test(dummy, 0)) == sizeof(yes))); \
\
typedef mpl::bool_<value> type; \
};
# else
# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
template <class T> \
struct is_##name : mpl::false_ \
{ \
}; \
\
template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class T) > \
struct is_##name< \
qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, T) > \
> \
: mpl::true_ \
{ \
};
# endif
#endif // IS_XXX_DWA2003224_HPP

View File

@@ -22,26 +22,6 @@
#ifdef _DEBUG
# ifndef BOOST_DEBUG_PYTHON
# ifdef _MSC_VER
// VC8.0 will complain if system headers are #included both with
// and without _DEBUG defined, so we have to #include all the
// system headers used by pyconfig.h right here.
# include <stddef.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# include <errno.h>
# include <ctype.h>
# include <wchar.h>
# include <basetsd.h>
# include <io.h>
# include <limits.h>
# include <float.h>
# include <string.h>
# include <math.h>
# include <time.h>
# endif
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# endif
@@ -117,7 +97,7 @@ typedef int pid_t;
# define HAVE_LONG_LONG 1
# define LONG_LONG long long
# endif
# endif
# elif defined(__MWERKS__)
@@ -163,10 +143,6 @@ typedef int pid_t;
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# define _DEBUG
# ifdef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST
# endif
#endif
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2

View File

@@ -363,7 +363,7 @@ namespace detail
, char const* doc
, detail::keyword_range keywords)
{
detail::def_init_aux(cl, args, NArgs(), policies, 0, keywords);
detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
if (keywords.second > keywords.first)
--keywords.second;

View File

@@ -23,13 +23,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
// return the next holder in a chain
instance_holder* next() const;
// When the derived holder actually holds by [smart] pointer and
// null_ptr_only is set, only report that the type is held when
// the pointer is null. This is needed for proper shared_ptr
// support, to prevent holding shared_ptrs from being found when
// converting from python so that we can use the conversion method
// that always holds the Python object.
virtual void* holds(type_info, bool null_ptr_only) = 0;
virtual void* holds(type_info) = 0;
void install(PyObject* inst) throw();

View File

@@ -34,10 +34,8 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
void enable_pickling_(bool getstate_manages_dict);
protected:
void add_property(
char const* name, object const& fget, char const* docstr);
void add_property(char const* name,
object const& fget, object const& fset, char const* docstr);
void add_property(char const* name, object const& fget);
void add_property(char const* name, object const& fget, object const& fset);
void add_static_property(char const* name, object const& fget);
void add_static_property(char const* name, object const& fget, object const& fset);

View File

@@ -30,10 +30,6 @@
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/single_view.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/noncopyable.hpp>
@@ -53,12 +49,6 @@ struct register_base_of
template <class Base>
inline void operator()(Base*) const
{
# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
# else
BOOST_STATIC_ASSERT(!(is_same<Base,Derived>::value));
# endif
// Register the Base class
register_dynamic_id<Base>();
@@ -68,7 +58,7 @@ struct register_base_of
// Register the down-cast, if appropriate.
this->register_downcast((Base*)0, is_polymorphic<Base>());
}
private:
static inline void register_downcast(void*, mpl::false_) {}
@@ -196,7 +186,7 @@ struct class_metadata
, mpl::if_<
use_value_holder
, value_holder<T>
, pointer_holder<held_type,wrapped>
, pointer_holder<held_type,T>
>
>::type holder;
@@ -209,8 +199,7 @@ struct class_metadata
template <class T2>
inline static void register_aux(python::wrapper<T2>*)
{
typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
class_metadata::register_aux2((T2*)0, use_callback());
class_metadata::register_aux2((T2*)0, mpl::true_());
}
inline static void register_aux(void*)
@@ -253,7 +242,6 @@ struct class_metadata
//
inline static void maybe_register_class_to_python(void*, mpl::true_) {}
template <class T2>
inline static void maybe_register_class_to_python(T2*, mpl::false_)
{

View File

@@ -10,11 +10,8 @@
namespace boost { namespace python { namespace objects {
// Given a type_id, find the instance data which corresponds to it, or
// return 0 in case no such type is held. If null_shared_ptr_only is
// true and the type being sought is a shared_ptr, only find an
// instance if it turns out to be NULL. Needed for shared_ptr rvalue
// from_python support.
BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, type_info, bool null_shared_ptr_only = false);
// return 0 in case no such type is held.
BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, type_info);
}}} // namespace boost::python::objects

View File

@@ -109,7 +109,7 @@ struct iterator_range
namespace detail
{
// Get a Python class which contains the given iterator and
// policies, creating it if necessary. Requires: NextPolicies is
// policies, creating it if neccessary. Requires: NextPolicies is
// default-constructible.
template <class Iterator, class NextPolicies>
object demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies())

View File

@@ -65,7 +65,7 @@ struct pointer_holder : instance_holder
private: // types
private: // required holder implementation
void* holds(type_info, bool null_ptr_only);
void* holds(type_info);
template <class T>
inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p)
@@ -99,7 +99,7 @@ struct pointer_holder_back_reference : instance_holder
# include BOOST_PP_ITERATE()
private: // required holder implementation
void* holds(type_info, bool null_ptr_only);
void* holds(type_info);
private: // data members
Pointer m_p;
@@ -120,11 +120,9 @@ inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_referen
}
template <class Pointer, class Value>
void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
void* pointer_holder<Pointer, Value>::holds(type_info dst_t)
{
if (dst_t == python::type_id<Pointer>()
&& !(null_ptr_only && get_pointer(this->m_p))
)
if (dst_t == python::type_id<Pointer>())
return &this->m_p;
Value* p = get_pointer(this->m_p);
@@ -139,11 +137,9 @@ void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
}
template <class Pointer, class Value>
void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
{
if (dst_t == python::type_id<Pointer>()
&& !(null_ptr_only && get_pointer(this->m_p))
)
if (dst_t == python::type_id<Pointer>())
return &this->m_p;
if (!get_pointer(this->m_p))

View File

@@ -29,8 +29,6 @@
# include <boost/preprocessor/repetition/enum_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
# include <boost/utility/addressof.hpp>
namespace boost { namespace python { namespace objects {
# if BOOST_WORKAROUND(__GNUC__, == 2)
@@ -50,7 +48,7 @@ struct value_holder : instance_holder
# include BOOST_PP_ITERATE()
private: // required holder implementation
void* holds(type_info, bool null_ptr_only);
void* holds(type_info);
template <class T>
inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p)
@@ -77,7 +75,7 @@ struct value_holder_back_reference : instance_holder
# include BOOST_PP_ITERATE()
private: // required holder implementation
void* holds(type_info, bool null_ptr_only);
void* holds(type_info);
private: // data members
Held m_held;
@@ -86,19 +84,19 @@ private: // required holder implementation
# undef BOOST_PYTHON_UNFORWARD_LOCAL
template <class Value>
void* value_holder<Value>::holds(type_info dst_t, bool null_ptr_only)
void* value_holder<Value>::holds(type_info dst_t)
{
if (void* wrapped = holds_wrapped(dst_t, boost::addressof(m_held), boost::addressof(m_held)))
if (void* wrapped = holds_wrapped(dst_t, &m_held, &m_held))
return wrapped;
type_info src_t = python::type_id<Value>();
return src_t == dst_t ? boost::addressof(m_held)
: find_static_type(boost::addressof(m_held), src_t, dst_t);
return src_t == dst_t ? &m_held
: find_static_type(&m_held, src_t, dst_t);
}
template <class Value, class Held>
void* value_holder_back_reference<Value,Held>::holds(
type_info dst_t, bool null_ptr_only)
type_info dst_t)
{
type_info src_t = python::type_id<Value>();
Value* x = &m_held;
@@ -134,7 +132,7 @@ void* value_holder_back_reference<Value,Held>::holds(
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
)
{
python::detail::initialize_wrapper(self, boost::addressof(this->m_held));
python::detail::initialize_wrapper(self, &this->m_held);
}
# undef N

View File

@@ -383,9 +383,9 @@ namespace api
template <>
struct object_initializer_impl<false, true>
{
template <class T, class U>
template <class T>
static PyObject*
get(T const& x, U)
get(T const& x, ...)
{
return python::incref(get_managed_object(x, tag));
}

View File

@@ -46,24 +46,12 @@ namespace detail
return converter(m_obj.release());
}
# if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(140050215))
template <class T>
operator T*()
{
converter::return_from_python<T*> converter;
return converter(m_obj.release());
}
# endif
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(_MSC_FULL_VER, <= 140040607) || BOOST_WORKAROUND(BOOST_INTEL_WIN, >= 900)
// No operator T&
# else
# if !defined(BOOST_MSVC) || BOOST_WORKAROUND(_MSC_FULL_VER, > 140040607)
template <class T>
operator T&() const
{
converter::return_from_python<T&> converter;
return converter(const_cast<handle<>&>(m_obj).release());
return converter(m_obj.release());
}
# endif

View File

@@ -70,8 +70,10 @@ namespace detail
: m_pmf(pmf)
{}
#if !BOOST_WORKAROUND(__EDG_VERSION__, <= 245)
private:
friend class python::def_visitor_access;
#endif
friend class def_visitor_access;
template <class C_, class Options>
void visit(C_& c, char const* name, Options& options) const

View File

@@ -11,7 +11,8 @@
# include <boost/get_pointer.hpp>
# include <boost/detail/binary_search.hpp>
# include <boost/numeric/conversion/cast.hpp>
# include <boost/type_traits/is_pointer.hpp>
# include <boost/detail/workaround.hpp>
# include <boost/config.hpp>
# include <vector>
# include <map>
#include <iostream>
@@ -463,29 +464,13 @@ namespace boost { namespace python { namespace detail {
{
}
template <class DataType>
static object
base_get_item_helper(DataType const& p, mpl::true_)
{
return object(ptr(p));
}
template <class DataType>
static object
base_get_item_helper(DataType const& x, mpl::false_)
{
return object(x);
}
static object
base_get_item_(back_reference<Container&> const& container, PyObject* i)
{
return base_get_item_helper(
return object(
DerivedPolicies::get_item(
container.get(), DerivedPolicies::
convert_index(container.get(), i))
, is_pointer<BOOST_DEDUCED_TYPENAME Container::value_type>()
);
convert_index(container.get(), i)));
}
static void
@@ -605,9 +590,17 @@ namespace boost { namespace python { namespace detail {
from += max_index;
if (from < 0) // Clip lower bounds to zero
from = 0;
if (from > max_index) // Clip upper bounds to max_index.
from = max_index;
// agurt 21/sep/04: here and below -- MSVC 6.x ICEs in 'vector_indexing_suite.cpp'
// unless we get skip 'boost::numeric_cast' layer and directly invoke the
// underlaying convertor's method
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
from_ = boost::numeric_cast<Index>(from);
if (from_ > max_index) // Clip upper bounds to max_index.
from_ = max_index;
#else
from_ = boost::numeric::converter<Index,long>::convert(from);
#endif
}
if (Py_None == slice->stop) {
@@ -619,9 +612,14 @@ namespace boost { namespace python { namespace detail {
to += max_index;
if (to < 0)
to = 0;
if (to > max_index)
to = max_index;
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
to_ = boost::numeric_cast<Index>(to);
if (to_ > max_index)
to_ = max_index;
#else
to_ = boost::numeric::converter<Index,long>::convert(to);
#endif
}
}

View File

@@ -1,7 +1,3 @@
25 April 2005
- Fixed bug where the code for wrappers of member functions were defined outside
the pyste namespace. Reported by Dan Haffey.
9 October 2004
- Applied a patch by Christian Hudon that fixed an issue with files
that had a tail and relative includes.

View File

@@ -253,11 +253,8 @@ class ClassExporter(Exporter):
return init
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
# don't export copy constructors if the class is abstract
# we could remove all constructors, but this will have the effect of
# inserting no_init in the declaration, which would not allow
# even subclasses to be instantiated.
self.constructors = constructors[:]
# don't export constructors if the class is abstract
if self.class_.abstract:
for cons in constructors:
if cons.IsCopy():
@@ -280,7 +277,6 @@ class ClassExporter(Exporter):
for cons in constructors:
code = '.def(%s)' % init_code(cons)
self.Add('inside', code)
# check if the class is copyable
if not self.class_.HasCopyConstructor() or self.class_.abstract:
self.Add('template', namespaces.boost + 'noncopyable')
@@ -396,7 +392,7 @@ class ClassExporter(Exporter):
# add wrapper code if this method has one
wrapper = method_info.wrapper
if wrapper and wrapper.code:
self.Add('declaration', wrapper.code)
self.Add('declaration-outside', wrapper.code)
# export staticmethod statements
for name in staticmethods:

View File

@@ -4,12 +4,7 @@
# http:#www.boost.org/LICENSE_1_0.txt)
from declarations import *
# try to use cElementTree if avaiable
try:
from cElementTree import ElementTree
except ImportError:
# fall back to the normal elementtree
from elementtree.ElementTree import ElementTree
from elementtree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError
from copy import deepcopy
from utils import enumerate
@@ -408,8 +403,12 @@ class GCCXMLParser(object):
classname = self.GetDecl(element.get('context')).FullName()
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
artificial = element.get('artificial', False)
ctor = Constructor(name, classname, params, visib)
artificial = element.get('artificial', False)
if not artificial:
ctor = Constructor(name, classname, params, visib)
else:
# we don't want artificial constructors
ctor = Unknown('__Unknown_Element_%s' % id)
ctor.location = location
self.Update(id, ctor)

View File

@@ -5,6 +5,3 @@
*.arg
*.dll
.sconsign
cache
*.cpp
*.pch

View File

@@ -8,8 +8,8 @@ sys.path.append('../src')
import unittest
import tempfile
import os.path
from Pyste import GCCXMLParser
from Pyste.declarations import *
import GCCXMLParser
from declarations import *
class Tester(unittest.TestCase):

View File

@@ -3,14 +3,13 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http:#www.boost.org/LICENSE_1_0.txt)
import sys
from Pyste.infos import *
from Pyste.policies import *
from Pyste.exporterutils import *
sys.path.append('../src')
from infos import *
from policies import *
from exporterutils import *
import unittest
#================================================================================
# InfosTest
#================================================================================
class InfosTest(unittest.TestCase):
def testFunctionInfo(self):

View File

@@ -8,7 +8,6 @@ namespace inherit3 {
struct A
{
A() { x = 0; }
struct X { int y; };
int x;
virtual int foo() { return 0; }
@@ -25,7 +24,6 @@ struct A
struct B: A
{
B() { x = 0; }
struct X { int y; };
int x;
int foo() { return 1; }

View File

@@ -3,13 +3,10 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http:#www.boost.org/LICENSE_1_0.txt)
import sys
sys.path.append('../src')
import unittest
from Pyste.policies import *
from policies import *
#================================================================================
# PolicicesTest
#================================================================================
class PoliciesTest(unittest.TestCase):
def testReturnInternal(self):

View File

@@ -1,7 +1,7 @@
#!/usr/bin/python
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to 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
# http:#www.boost.org/LICENSE_1_0.txt)
import os
@@ -14,28 +14,28 @@ import time
# win32 configuration
#=============================================================================
if sys.platform == 'win32':
includes = '-ID:/programming/libraries/boost-cvs/boost -ID:/Bin/Python/include'
build_pyste_cmd = 'python ../src/Pyste/pyste.py --pyste-ns=pyste --cache-dir=cache %s ' % includes
build_pyste_cmd = 'python ../src/Pyste/pyste.py --cache-dir=cache %s ' % includes
compile_single_cmd = 'cl /nologo /GR /GX -c %s -I. ' % includes
link_single_cmd = 'link /nologo /DLL '\
'/libpath:D:/programming/libraries/boost-cvs/lib /libpath:D:/Bin/Python/libs '\
'boost_python.lib python24.lib /out:_%s.dll '
'boost_python.lib python23.lib /out:_%s.dll '
obj_ext = 'obj'
#=============================================================================
# linux configuration
#=============================================================================
#=============================================================================
elif sys.platform == 'linux2':
build_pyste_cmd = 'python ../src/Pyste/pyste.py -I. '
compile_single_cmd = 'g++ -shared -c -I. -I/usr/include/python2.4 '
compile_single_cmd = 'g++ -shared -c -I. -I/usr/include/python2.2 '
link_single_cmd = 'g++ -shared -o _%s.so -lboost_python '
obj_ext = 'o'
def build_pyste(multiple, module):
def build_pyste(multiple, module):
rest = '%s --module=_%s %s.pyste' % (multiple, module, module)
execute(build_pyste_cmd + rest)
@@ -67,8 +67,8 @@ def compile_multiple(module):
def execute(cmd):
os.system(cmd)
def run_tests():
if os.system('python runtests.py') != 0:
raise RuntimeError, 'tests failed'
@@ -93,36 +93,36 @@ def cleanup():
shutil.rmtree('_' + module)
except OSError: pass
def main(multiple, module=None):
if module is None:
modules = get_modules()
else:
modules = [module]
start = time.clock()
for module in modules:
build_pyste(multiple, module)
for module in modules:
build_pyste(multiple, module)
print '-'*50
print 'Building pyste files: %0.2f seconds' % (time.clock()-start)
print
start = time.clock()
for module in modules:
if multiple:
compile_multiple(module)
else:
compile_single(module)
compile_single(module)
print '-'*50
print 'Compiling files: %0.2f seconds' % (time.clock()-start)
print 'Compiling files: %0.2f seconds' % (time.clock()-start)
print
if len(modules) == 1:
os.system('python %sUT.py' % modules[0])
else:
run_tests()
#cleanup()
#cleanup()
def get_modules():
def getname(file):
return os.path.splitext(os.path.basename(file))[0]
@@ -137,4 +137,4 @@ if __name__ == '__main__':
# main('--multiple', module)
main('', module)
except RuntimeError, e:
print e
print e

View File

@@ -74,15 +74,8 @@ namespace
// Get the location in which to construct
void* storage = ((rvalue_from_python_storage<T>*)data)->storage.bytes;
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4244)
# endif
new (storage) T( SlotPolicy::extract(intermediate.get()) );
# ifdef _MSC_VER
# pragma warning(pop)
# endif
new (storage) T(SlotPolicy::extract(intermediate.get()));
// record successful construction
data->convertible = storage;
}

View File

@@ -43,7 +43,7 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
// First check to see if it's embedded in an extension class
// instance, as a special case.
data.convertible = objects::find_instance_impl(source, converters.target_type, converters.is_shared_ptr);
data.convertible = objects::find_instance_impl(source, converters.target_type);
if (data.convertible)
{
data.construct = 0;

View File

@@ -8,6 +8,7 @@
#include <set>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \
&& __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__)
@@ -127,7 +128,7 @@ namespace // <unnamed>
}
#endif // BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
entry* get(type_info type, bool is_shared_ptr = false)
entry* get(type_info type)
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
registry_t::iterator p = entries().find(entry(type));
@@ -137,7 +138,7 @@ namespace // <unnamed>
? "...NOT found\n" : "...found\n");
# endif
std::pair<registry_t::const_iterator,bool> pos_ins
= entries().insert(entry(type,is_shared_ptr));
= entries().insert(entry(type));
# if __MWERKS__ >= 0x3000
// do a little invariant checking if a change was made
@@ -160,9 +161,9 @@ namespace registry
assert(slot == 0); // we have a problem otherwise
if (slot != 0)
{
std::string msg = (
std::string("to-Python converter for ")
+ source_t.name()
std::string msg(
"to-Python converter for "
+ lexical_cast<std::string>(source_t)
+ " already registered; second conversion method ignored."
);
@@ -229,11 +230,6 @@ namespace registry
return *get(key);
}
registration const& lookup_shared_ptr(type_info key)
{
return *get(key, true);
}
registration const* query(type_info type)
{
registry_t::iterator p = entries().find(entry(type));

View File

@@ -407,7 +407,7 @@ namespace objects
}
BOOST_PYTHON_DECL void*
find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
find_instance_impl(PyObject* inst, type_info type)
{
if (inst->ob_type->ob_type != &class_metatype_object)
return 0;
@@ -416,7 +416,7 @@ namespace objects
for (instance_holder* match = self->objects; match != 0; match = match->next())
{
void* const found = match->holds(type, null_shared_ptr_only);
void* const found = match->holds(type);
if (found)
return found;
}
@@ -535,22 +535,20 @@ namespace objects
this->attr("__instance_size__") = instance_size;
}
void class_base::add_property(
char const* name, object const& fget, char const* docstr)
void class_base::add_property(char const* name, object const& fget)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction((PyObject*)&PyProperty_Type, "Osss", fget.ptr(), 0, 0, docstr));
PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.ptr()));
this->setattr(name, property);
}
void class_base::add_property(
char const* name, object const& fget, object const& fset, char const* docstr)
void class_base::add_property(char const* name, object const& fget, object const& fset)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction((PyObject*)&PyProperty_Type, "OOss", fget.ptr(), fset.ptr(), 0, docstr));
PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.ptr(), fset.ptr()));
this->setattr(name, property);
}

View File

@@ -404,7 +404,7 @@ void function::add_to_namespace(
dict = ((PyClassObject*)ns)->cl_dict;
else if (PyType_Check(ns))
dict = ((PyTypeObject*)ns)->tp_dict;
else
else
dict = PyObject_GetAttrString(ns, "__dict__");
if (dict == 0)
@@ -471,18 +471,8 @@ void function::add_to_namespace(
add_to_namespace(name_space, name_, attribute);
if (doc != 0)
{
// Accumulate documentation
object mutable_attribute(attribute);
if (
PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
&& mutable_attribute.attr("__doc__"))
{
mutable_attribute.attr("__doc__") += "\n\n";
mutable_attribute.attr("__doc__") += doc;
}
else
mutable_attribute.attr("__doc__") = doc;
object attr_copy(attribute);
attr_copy.attr("__doc__") = doc;
}
}
@@ -576,20 +566,11 @@ extern "C"
else
return python::incref(f->name().ptr());
}
// We add a dummy __class__ attribute in order to fool PyDoc into
// treating these as built-in functions and scanning their
// documentation
static PyObject* function_get_class(PyObject* op, void*)
{
return python::incref(upcast<PyObject>(&PyCFunction_Type));
}
}
static PyGetSetDef function_getsetlist[] = {
{"__name__", (getter)function_get_name, 0 },
{"func_name", (getter)function_get_name, 0 },
{"__class__", (getter)function_get_class, 0 }, // see note above
{"__doc__", (getter)function_get_doc, (setter)function_set_doc},
{"func_doc", (getter)function_get_doc, (setter)function_set_doc},
{NULL} /* Sentinel */

View File

@@ -203,7 +203,7 @@ namespace
return &*p;
}
// Get the entry for a type, inserting if necessary
// Get the entry for a type, inserting if neccessary
inline type_index_t::iterator demand_type(class_id type)
{
type_index_t::iterator p = type_position(type);
@@ -218,7 +218,7 @@ namespace
return type_index().insert(p, boost::make_tuple(type, v, dynamic_id_function(0)));
}
// Map a two types to a vertex in the graph, inserting if necessary
// Map a two types to a vertex in the graph, inserting if neccessary
typedef std::pair<type_index_t::iterator, type_index_t::iterator>
type_index_iterator_pair;

View File

@@ -98,17 +98,11 @@ bpl-test crossmod_exception
[ bpl-test return_arg ]
[ bpl-test staticmethod ]
[ bpl-test shared_ptr ]
[ bpl-test andreas_beyer ]
[ bpl-test polymorphism ]
[ bpl-test polymorphism2 ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr ]
[ bpl-test auto_ptr ]
[ bpl-test minimal ]
[ bpl-test args ]
[ bpl-test raw_ctor ]
[ bpl-test numpy ]
[ bpl-test enum ]
[ bpl-test exception_translator ]
@@ -119,7 +113,7 @@ bpl-test crossmod_exception
[ bpl-test keywords : keywords.cpp keywords_test.py ]
[ extension builtin_converters : test_builtin_converters.cpp <template>../build/extension ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters : : : -v ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ]
[ bpl-test test_pointer_adoption ]
[ bpl-test operators ]
@@ -166,13 +160,11 @@ bpl-test crossmod_exception
[ bpl-test docstring ]
[ bpl-test vector_indexing_suite ]
[ bpl-test pointer_vector ]
[ extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp <template>../build/extension ]
#[ boost-python-runtest
# map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext : : : -v ]
[ boost-python-runtest
map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext ]
# if $(TEST_BIENSTMAN_NON_BUGS)
# {
@@ -182,9 +174,9 @@ bpl-test crossmod_exception
# --- unit tests of library components ---
[ compile indirect_traits_test.cpp ]
[ run indirect_traits_test.cpp ]
[ run destroy_test.cpp ]
[ run pointer_type_id_test.cpp <template>py-unit-test ]
[ run pointer_type_id_test.cpp <lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ run bases.cpp <template>py-unit-test ]
[ run if_else.cpp ]
[ run pointee.cpp <template>py-unit-test ]
@@ -195,12 +187,12 @@ bpl-test crossmod_exception
[ compile object_manager.cpp <template>py-unit-test ]
[ compile copy_ctor_mutates_rhs.cpp <template>py-unit-test ]
[ run upcast.cpp <template>py-unit-test ]
[ run upcast.cpp <lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ compile select_holder.cpp <template>py-unit-test ]
[ run select_from_python_test.cpp ../src/converter/type_id.cpp
<template>py-unit-test ]
<lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ compile select_arg_to_python_test.cpp <template>py-unit-test ]

View File

@@ -1,160 +0,0 @@
use-project /boost/python : ../build ;
project /boost/python/test ;
# A bug in the Win32 intel compilers causes compilation of one of our
# tests to take forever when debug symbols are enabled. This rule
# turns them off when added to the requirements section
#rule turn-off-intel-debug-symbols ( toolset variant : properties * )
#{
# if $(NT) && [ MATCH (.*intel.*) : $(toolset) ]
# {
# properties = [ difference $(properties) : <debug-symbols>on ] <debug-symbols>off ;
# }
# return $(properties) ;
#}
rule py-run ( sources * )
{
return [ run $(sources) /boost/python//boost_python ] ;
}
rule py-compile ( sources * )
{
return [ compile $(sources) /boost/python//boost_python ] ;
}
rule py-compile-fail ( sources * )
{
return [ compile-fail $(sources) /boost/python//boost_python ] ;
}
#template py-unit-test
# :
# : $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
# [ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ] <define>BOOST_PYTHON_STATIC_LIB
# ;
test-suite python
:
[ run ../test/embedding.cpp ../build//boost_python /python//python ]
[
bpl-test crossmod_exception
: crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp
]
[ bpl-test injected ]
[ bpl-test properties ]
[ bpl-test return_arg ]
[ bpl-test staticmethod ]
[ bpl-test shared_ptr ]
[ bpl-test polymorphism ]
[ bpl-test polymorphism2 ]
[ bpl-test auto_ptr ]
[ bpl-test minimal ]
[ bpl-test args ]
[ bpl-test raw_ctor ]
[ bpl-test numpy ]
[ bpl-test enum ]
[ bpl-test exception_translator ]
[ bpl-test pearu1 : test_cltree.py cltree.cpp ]
[ bpl-test try : newtest.py m1.cpp m2.cpp ]
[ bpl-test const_argument ]
[ bpl-test keywords : keywords.cpp keywords_test.py ]
[ python-extension builtin_converters : test_builtin_converters.cpp /boost/python//boost_python ]
[ bpl-test builtin_converters_test : test_builtin_converters.py builtin_converters ]
[ bpl-test test_pointer_adoption ]
[ bpl-test operators ]
[ bpl-test callbacks ]
[ bpl-test defaults ]
[ bpl-test object ]
[ bpl-test list ]
[ bpl-test long ]
[ bpl-test dict ]
[ bpl-test tuple ]
[ bpl-test str ]
[ bpl-test slice ]
[ bpl-test virtual_functions ]
[ bpl-test back_reference ]
[ bpl-test implicit ]
[ bpl-test data_members ]
[ bpl-test ben_scott1 ]
[ bpl-test bienstman1 ]
[ bpl-test bienstman2 ]
[ bpl-test bienstman3 ]
#
#[ bpl-test multi_arg_constructor
# : # files
# : # requirements
# turn-off-intel-debug-symbols ] # debug symbols slow the build down too much
#
[ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ]
[ bpl-test extract ]
[ bpl-test opaque ]
[ bpl-test pickle1 ]
[ bpl-test pickle2 ]
[ bpl-test pickle3 ]
[ bpl-test pickle4 ]
[ bpl-test nested ]
[ bpl-test docstring ]
[ bpl-test vector_indexing_suite ]
[ bpl-test pointer_vector ]
[ python-extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp
/boost/python//boost_python ]
[ bpl-test
map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ]
# if $(TEST_BIENSTMAN_NON_BUGS)
# {
# bpl-test bienstman4 ;
# bpl-test bienstman5 ;
# }
# --- unit tests of library components ---
[ run indirect_traits_test.cpp ]
[ run destroy_test.cpp ]
[ py-run pointer_type_id_test.cpp ]
[ py-run bases.cpp ]
[ run if_else.cpp ]
[ py-run pointee.cpp ]
[ run result.cpp ]
[ compile string_literal.cpp ]
[ py-compile borrowed.cpp ]
[ py-compile object_manager.cpp ]
[ py-compile copy_ctor_mutates_rhs.cpp ]
[ py-run upcast.cpp ]
[ py-compile select_holder.cpp ]
[ py-run select_from_python_test.cpp ../src/converter/type_id.cpp ]
[ py-compile select_arg_to_python_test.cpp ]
[ py-compile-fail ./raw_pyobject_fail1.cpp ]
[ py-compile-fail ./raw_pyobject_fail2.cpp ]
[ py-compile-fail ./as_to_python_function.cpp ]
[ py-compile-fail ./object_fail1.cpp ]
;

View File

@@ -1,58 +0,0 @@
#include <boost/python.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
using namespace boost;
class A : public enable_shared_from_this<A> {
public:
A() : val(0) {};
int val;
typedef shared_ptr<A> A_ptr;
A_ptr self() {
A_ptr self;
self = shared_from_this();
return self;
}
};
class B {
public:
B() {
a = A::A_ptr(new A());
}
void set(A::A_ptr a) {
this->a = a;
}
A::A_ptr get() {
return a;
}
A::A_ptr a;
};
template <class T>
void hold_python(shared_ptr<T>& x)
{
x = python::extract<shared_ptr<T> >( python::object(x) );
}
A::A_ptr get_b_a(shared_ptr<B> b)
{
hold_python(b->a);
return b->get();
}
BOOST_PYTHON_MODULE(andreas_beyer_ext) {
python::class_<A, noncopyable> ("A")
.def("self", &A::self)
.def_readwrite("val", &A::val)
;
python::register_ptr_to_python< A::A_ptr >();
python::class_<B>("B")
.def("set", &B::set)
// .def("get", &B::get)
.def("get", get_b_a)
;
}

View File

@@ -1,24 +0,0 @@
# Copyright David Abrahams 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)
'''
>>> from andreas_beyer_ext import *
>>> b=B()
>>> a=b.get() # let b create an A
>>> a2=b.get()
>>> assert id(a) == id(a2)
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
status = run()[0]
if (status == 0): print "Done."
sys.exit(status)

View File

@@ -1,7 +1,3 @@
// Copyright David Abrahams 2005. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>

View File

@@ -47,8 +47,6 @@ BOOST_PYTHON_MODULE(docstring_ext)
)
.def("value", &X::value,
"gets the value of the object")
.def( "value", &X::value,
"also gets the value of the object")
;
def("create", create, return_value_policy<manage_new_object>(),

View File

@@ -15,6 +15,9 @@ includes some error-checking
this is the __init__ function
its documentation has two lines.
>>> printdoc(X.value)
gets the value of the object
>>> printdoc(create)
creates a new X object
@@ -22,13 +25,6 @@ creates a new X object
compute the factorial
'''
def check_double_string():
"""
>>> assert check_double_string() == True
"""
from docstring_ext import X
return X.value.__doc__ == "gets the value of the object\n\nalso gets the value of the object"
def run(args = None):
import sys
import doctest

View File

@@ -63,6 +63,10 @@ void test()
if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules");
// Initialize the interpreter
Py_Initialize();
// Retrieve the main module
python::object main_module((
python::handle<>(python::borrowed(PyImport_AddModule("__main__")))));
@@ -101,7 +105,7 @@ void test()
// as easy!
python::object py_base = PythonDerived();
Base& py = python::extract<Base&>(py_base)
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 810)
()
#endif
;
@@ -165,9 +169,6 @@ test_tutorial2()
int main()
{
// Initialize the interpreter
Py_Initialize();
if (python::handle_exception(test))
{
if (PyErr_Occurred())
@@ -189,8 +190,6 @@ int main()
return 1;
}
// Boost.Python doesn't support Py_Finalize yet.
// Py_Finalize();
return 0;
}
#include "module_tail.cpp"

View File

@@ -50,7 +50,7 @@ std::string const& extract_string_cref(object x)
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
# pragma warning(push)
# pragma warning(disable:4172) // msvc lies about returning a reference to temporary
#elif defined(_MSC_VER) && defined(__ICL) && __ICL <= 900
#elif defined(_MSC_VER) && defined(__ICL) && __ICL <= 800
# pragma warning(push)
# pragma warning(disable:473) // intel/win32 does too
#endif

View File

@@ -3,114 +3,106 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//#include <stdio.h>
#include <cassert>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/python/detail/indirect_traits.hpp>
#include <boost/mpl/assert.hpp>
//#define print(expr) printf("%s ==> %s\n", #expr, expr)
// not all the compilers can handle an incomplete class type here.
struct X {};
using namespace boost::python::indirect_traits;
int main()
{
using namespace boost::python::indirect_traits;
typedef void (X::*pmf)();
typedef void (X::*pmf)();
BOOST_MPL_ASSERT((is_reference_to_function<int (&)()>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function<int (*)()>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function<int&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function<pmf>));
assert(is_reference_to_function<int (&)()>::value);
assert(!is_reference_to_function<int (*)()>::value);
assert(!is_reference_to_function<int&>::value);
assert(!is_reference_to_function<pmf>::value);
BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (&)()>));
BOOST_MPL_ASSERT((is_pointer_to_function<int (*)()>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (*&)()>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (*const&)()>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_function<pmf>));
assert(!is_pointer_to_function<int (&)()>::value);
assert(is_pointer_to_function<int (*)()>::value);
assert(!is_pointer_to_function<int (*&)()>::value);
assert(!is_pointer_to_function<int (*const&)()>::value);
assert(!is_pointer_to_function<pmf>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int (&)()>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int (*)()>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int&>));
BOOST_MPL_ASSERT((is_reference_to_function_pointer<int (*&)()>));
BOOST_MPL_ASSERT((is_reference_to_function_pointer<int (*const&)()>));
BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<pmf>));
assert(!is_reference_to_function_pointer<int (&)()>::value);
assert(!is_reference_to_function_pointer<int (*)()>::value);
assert(!is_reference_to_function_pointer<int&>::value);
assert(is_reference_to_function_pointer<int (*&)()>::value);
assert(is_reference_to_function_pointer<int (*const&)()>::value);
assert(!is_reference_to_function_pointer<pmf>::value);
BOOST_MPL_ASSERT((is_reference_to_pointer<int*&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int* const&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int*volatile&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int*const volatile&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int const*&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int const* const&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int const*volatile&>));
BOOST_MPL_ASSERT((is_reference_to_pointer<int const*const volatile&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<pmf>));
assert(is_reference_to_pointer<int*&>::value);
assert(is_reference_to_pointer<int* const&>::value);
assert(is_reference_to_pointer<int*volatile&>::value);
assert(is_reference_to_pointer<int*const volatile&>::value);
assert(is_reference_to_pointer<int const*&>::value);
assert(is_reference_to_pointer<int const* const&>::value);
assert(is_reference_to_pointer<int const*volatile&>::value);
assert(is_reference_to_pointer<int const*const volatile&>::value);
assert(!is_reference_to_pointer<pmf>::value);
assert(!is_reference_to_pointer<int const volatile>::value);
assert(!is_reference_to_pointer<int>::value);
assert(!is_reference_to_pointer<int*>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int const volatile>));
BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int>));
BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int*>));
assert(!is_reference_to_const<int*&>::value);
assert(is_reference_to_const<int* const&>::value);
assert(!is_reference_to_const<int*volatile&>::value);
assert(is_reference_to_const<int*const volatile&>::value);
assert(!is_reference_to_const<int const volatile>::value);
assert(!is_reference_to_const<int>::value);
assert(!is_reference_to_const<int*>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*&>));
BOOST_MPL_ASSERT((is_reference_to_const<int* const&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*volatile&>));
BOOST_MPL_ASSERT((is_reference_to_const<int*const volatile&>));
assert(is_reference_to_non_const<int*&>::value);
assert(!is_reference_to_non_const<int* const&>::value);
assert(is_reference_to_non_const<int*volatile&>::value);
assert(!is_reference_to_non_const<int*const volatile&>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_const<int const volatile>));
BOOST_MPL_ASSERT_NOT((is_reference_to_const<int>));
BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*>));
assert(!is_reference_to_non_const<int const volatile>::value);
assert(!is_reference_to_non_const<int>::value);
assert(!is_reference_to_non_const<int*>::value);
assert(!is_reference_to_volatile<int*&>::value);
assert(!is_reference_to_volatile<int* const&>::value);
assert(is_reference_to_volatile<int*volatile&>::value);
assert(is_reference_to_volatile<int*const volatile&>::value);
assert(!is_reference_to_volatile<int const volatile>::value);
assert(!is_reference_to_volatile<int>::value);
assert(!is_reference_to_volatile<int*>::value);
BOOST_MPL_ASSERT((is_reference_to_non_const<int*&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int* const&>));
BOOST_MPL_ASSERT((is_reference_to_non_const<int*volatile&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int*const volatile&>));
assert(!is_reference_to_class<int>::value);
assert(!is_reference_to_class<int&>::value);
assert(!is_reference_to_class<int*>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int const volatile>));
BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int>));
BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int*>));
assert(!is_reference_to_class<X>::value);
assert(is_reference_to_class<X&>::value);
assert(is_reference_to_class<X const&>::value);
assert(is_reference_to_class<X volatile&>::value);
assert(is_reference_to_class<X const volatile&>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int*&>));
BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int* const&>));
BOOST_MPL_ASSERT((is_reference_to_volatile<int*volatile&>));
BOOST_MPL_ASSERT((is_reference_to_volatile<int*const volatile&>));
assert(!is_pointer_to_class<int>::value);
assert(!is_pointer_to_class<int*>::value);
assert(!is_pointer_to_class<int&>::value);
BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int const volatile>));
BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int>));
BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int*>));
assert(!is_pointer_to_class<X>::value);
assert(!is_pointer_to_class<X&>::value);
assert(is_pointer_to_class<X*>::value);
assert(is_pointer_to_class<X const*>::value);
assert(is_pointer_to_class<X volatile*>::value);
assert(is_pointer_to_class<X const volatile*>::value);
namespace tt = boost::python::indirect_traits;
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int&>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int*>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<pmf>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<pmf const&>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<X>));
BOOST_MPL_ASSERT((tt::is_reference_to_class<X&>));
BOOST_MPL_ASSERT((tt::is_reference_to_class<X const&>));
BOOST_MPL_ASSERT((tt::is_reference_to_class<X volatile&>));
BOOST_MPL_ASSERT((tt::is_reference_to_class<X const volatile&>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int*>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int&>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<X>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<X&>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<pmf>));
BOOST_MPL_ASSERT_NOT((is_pointer_to_class<pmf const>));
BOOST_MPL_ASSERT((is_pointer_to_class<X*>));
BOOST_MPL_ASSERT((is_pointer_to_class<X const*>));
BOOST_MPL_ASSERT((is_pointer_to_class<X volatile*>));
BOOST_MPL_ASSERT((is_pointer_to_class<X const volatile*>));
BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf&>));
BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf const&>));
BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf volatile&>));
BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf const volatile&>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf[2]>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf(&)[2]>));
BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf>));
assert(is_reference_to_member_function_pointer<pmf&>::value);
assert(is_reference_to_member_function_pointer<pmf const&>::value);
assert(is_reference_to_member_function_pointer<pmf volatile&>::value);
assert(is_reference_to_member_function_pointer<pmf const volatile&>::value);
assert(!is_reference_to_member_function_pointer<pmf[2]>::value);
assert(!is_reference_to_member_function_pointer<pmf(&)[2]>::value);
assert(!is_reference_to_member_function_pointer<pmf>::value);
return 0;
}

View File

@@ -15,7 +15,6 @@
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4297)
# pragma warning(disable:4535)
extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
{
throw;

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