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

Compare commits

..

1 Commits

Author SHA1 Message Date
Beman Dawes
950ed457cd Branch at revision 46530
[SVN r46531]
2008-06-19 18:57:10 +00:00
112 changed files with 1571 additions and 3049 deletions

View File

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

View File

@@ -9,7 +9,7 @@
</head> </head>
<body> <body>
<div class="document" id="logo-boost-python-build-and-test-howto"> <div class="document" id="logo-boost-python-build-and-test-howto">
<h1 class="title"><a class="reference external" href="../index.html"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1> <h1 class="title"><a class="reference external" href="../index.htm"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
<!-- Copyright David Abrahams 2006. Distributed under the Boost --> <!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying --> <!-- Software License, Version 1.0. (See accompanying -->

View File

@@ -32,43 +32,7 @@
<hr> <hr>
<dl class="page-index"> <dl class="page-index">
<dt>Current SVN</dt> <dt>Current SVN</dt>
<dd>
<ul>
<li>Python 3 support:</li>
<ul>
<li>All the current Boost.Python test cases passed. Extension modules using
Boost.Python expected to support Python 3 smoothly.</li>
<li>Introduced <code>object.contains</code> where <code>x.contains(y)</code>
is equivalent to Python code <code>y in x</code>.
Now <code>dict.has_key</code> is just a wrapper of <code>object.contains</code>.
</li>
<li>When building against Python 3, <code>str.decode</code> will be removed.</li>
<li>When building against Python 3, the original signature of <code>list.sort</code>, which is:
<pre>void sort(object_cref cmpfunc);</pre>
will change to:
<pre>void sort(args_proxy const &args, kwds_proxy const &kwds);</pre>
This is because in Python 3 <code>list.sort</code> requires all its arguments be keyword arguments.
So you should call it like this:
<pre>x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));</pre>
</li>
<li>According to <a href="http://www.python.org/dev/peps/pep-3123/">PEP 3123</a>,
when building Boost.Python against Python older than 2.6, the following macros will
be defined in Boost.Python header:
<pre>
# define Py_TYPE(o) (((PyObject*)(o))->ob_type)
# define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt)
# define Py_SIZE(o) (((PyVarObject*)(o))->ob_size)</pre>
So extension writers can use these macro directly, to make code clean and compatible with Python 3.
</li>
</ul>
</ul>
</dd>
<dt>1.39.0 Release</dt>
<dd> <dd>
<ul> <ul>

View File

@@ -6,13 +6,11 @@ project boost/libs/python/doc/tutorial/doc ;
import boostbook : boostbook ; import boostbook : boostbook ;
using quickbook ; using quickbook ;
path-constant images : html ;
boostbook tutorial boostbook tutorial
: :
tutorial.qbk tutorial.qbk
: :
<xsl:param>boost.root=../../../../../.. <xsl:param>boost.root=../../../../../..
<format>pdf:<xsl:param>img.src.path=$(images)/ <xsl:param>boost.libraries=../../../../../../libs/libraries.htm
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/python/doc/tutorial/doc/html <xsl:param>html.stylesheet=../../../../../../doc/html/boostbook.css
; ;

View File

@@ -1,37 +1,37 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chapter&#160;1.&#160;python 2.0</title> <title>Chapter 1. python 1.0</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="index.html" title="Chapter 1. python 1.0">
<link rel="next" href="python/hello.html" title="Building Hello World"> <link rel="next" href="python/hello.html" title=" Building Hello World">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></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="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a></div> <div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
<div class="chapter"> <div class="chapter" lang="en">
<div class="titlepage"><div> <div class="titlepage"><div>
<div><h2 class="title"> <div><h2 class="title">
<a name="python"></a>Chapter&#160;1.&#160;python 2.0</h2></div> <a name="python"></a>Chapter 1. python 1.0</h2></div>
<div><div class="author"><h3 class="author"> <div><div class="author"><h3 class="author">
<span class="firstname">Joel</span> <span class="surname">de Guzman</span> <span class="firstname">Joel</span> <span class="surname">de Guzman</span>
</h3></div></div> </h3></div></div>
<div><div class="author"><h3 class="author"> <div><div class="author"><h3 class="author">
<span class="firstname">David</span> <span class="surname">Abrahams</span> <span class="firstname">David</span> <span class="surname">Abrahams</span>
</h3></div></div> </h3></div></div>
<div><p class="copyright">Copyright &#169; 2002-2005 Joel <div><p class="copyright">Copyright © 2002-2005 Joel
de Guzman, David Abrahams</p></div> de Guzman, David Abrahams</p></div>
<div><div class="legalnotice"> <div><div class="legalnotice">
<a name="id759709"></a><p> <a name="id455917"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
http://www.boost.org/LICENSE_1_0.txt </a>) http://www.boost.org/LICENSE_1_0.txt </a>)
@@ -79,7 +79,7 @@
</dl></dd> </dl></dd>
</dl> </dl>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.quickstart"></a>QuickStart</h2></div></div></div> <a name="python.quickstart"></a>QuickStart</h2></div></div></div>
<p> <p>
@@ -93,15 +93,16 @@
code takes on the look of a kind of declarative interface definition language code takes on the look of a kind of declarative interface definition language
(IDL). (IDL).
</p> </p>
<a name="quickstart.hello_world"></a><h3> <a name="quickstart.hello_world"></a><h2>
<a name="id759740"></a> <a name="id385257"></a>
Hello World Hello World
</h3> </h2>
<p> <p>
Following C/C++ tradition, let's start with the "hello, world". A Following C/C++ tradition, let's start with the "hello, world". A
C++ Function: C++ Function:
</p> </p>
<pre class="programlisting"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">greet</span><span class="special">()</span> <pre class="programlisting">
<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">greet</span><span class="special">()</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="string">"hello, world"</span><span class="special">;</span> <span class="keyword">return</span> <span class="string">"hello, world"</span><span class="special">;</span>
<span class="special">}</span> <span class="special">}</span>
@@ -109,7 +110,8 @@
<p> <p>
can be exposed to Python by writing a Boost.Python wrapper: can be exposed to Python by writing a Boost.Python wrapper:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello_ext</span><span class="special">)</span> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello_ext</span><span class="special">)</span>
<span class="special">{</span> <span class="special">{</span>
@@ -123,23 +125,30 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello_ext</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello_ext</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="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">hello</span><span class="special">,</span> <span class="identifier">world</span> <span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
</pre> </pre>
<p> <p>
</p> </p>
<div class="blockquote"><blockquote class="blockquote"><p> <div class="blockquote"><blockquote class="blockquote">
<span class="emphasis"><em><span class="bold"><strong>Next stop... Building your Hello World module <p>
from start to finish...</strong></span></em></span> </p>
</p></blockquote></div> <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>
<p>
</p>
</blockquote></div>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: July 01, 2010 at 21:56:58 GMT</small></p></td> <td align="left"><p><small>Last revised: November 07, 2007 at 03:34:24 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td> <td align="right"><div class="copyright-footer"></div></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a></div> <div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Embedding</title> <title>Embedding</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="object.html" title="Object Interface"> <link rel="prev" href="object.html" title=" Object Interface">
<link rel="next" href="iterators.html" title="Iterators"> <link rel="next" href="iterators.html" title="Iterators">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.embedding"></a>Embedding</h2></div></div></div> <a name="python.embedding"></a>Embedding</h2></div></div></div>
<div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div> <div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div>
@@ -39,28 +39,28 @@
a lot easier and, in a future version, it may become unnecessary to touch the 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" alt="smiley"></span> Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
</p> </p>
<a name="embedding.building_embedded_programs"></a><h3> <a name="embedding.building_embedded_programs"></a><h2>
<a name="id773307"></a> <a name="id471171"></a>
Building embedded programs Building embedded programs
</h3> </h2>
<p> <p>
To be able to embed python into your programs, you have to link to both Boost.Python's To be able to embed python into your programs, you have to link to both Boost.Python's
as well as Python's own runtime library. as well as Python's own runtime library.
</p> </p>
<p> <p>
Boost.Python's library comes in two variants. Both are located in Boost's Boost.Python's library comes in two variants. Both are located in Boost's
<code class="literal">/libs/python/build/bin-stage</code> subdirectory. On Windows, the <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
variants are called <code class="literal">boost_python.lib</code> (for release builds) variants are called <tt class="literal">boost_python.lib</tt> (for release builds)
and <code class="literal">boost_python_debug.lib</code> (for debugging). If you can't and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you can't
find the libraries, you probably haven't built Boost.Python yet. See <a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this. find the libraries, you probably haven't built Boost.Python yet. See <a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this.
</p> </p>
<p> <p>
Python's library can be found in the <code class="literal">/libs</code> subdirectory Python's library can be found in the <tt class="literal">/libs</tt> subdirectory
of your Python directory. On Windows it is called pythonXY.lib where X.Y is of your Python directory. On Windows it is called pythonXY.lib where X.Y is
your major Python version number. your major Python version number.
</p> </p>
<p> <p>
Additionally, Python's <code class="literal">/include</code> subdirectory has to be added Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
to your include path. to your include path.
</p> </p>
<p> <p>
@@ -81,65 +81,72 @@ exe embedded_program # name of the executable
&lt;library-path&gt;$(PYTHON_LIB_PATH) &lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ; &lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
</pre> </pre>
<a name="embedding.getting_started"></a><h3> <a name="embedding.getting_started"></a><h2>
<a name="id773391"></a> <a name="id471276"></a>
Getting started Getting started
</h3> </h2>
<p> <p>
Being able to build is nice, but there is nothing to build yet. Embedding the 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: Python interpreter into one of your C++ programs requires these 4 steps:
</p> </p>
<div class="orderedlist"><ol class="orderedlist" type="1"> <div class="orderedlist"><ol type="1">
<li class="listitem"> <li>
#include <code class="literal">&lt;boost/python.hpp&gt;</code> #include <tt class="literal">&lt;boost/python.hpp&gt;</tt>
</li> </li>
<li class="listitem"> <li>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>() 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 <code class="literal"><span class="underline">_main</span>_</code> to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
module. module.
</li> </li>
<li class="listitem"> <li>
Call other Python C API routines to use the interpreter. Call other Python C API routines to use the interpreter.
</li> </li>
</ol></div> </ol></div>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"><p> <tr><td colspan="2" align="left" valign="top"><p>
<span class="bold"><strong>Note that at this time you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>() <span class="bold"><b>Note that at this time you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
to stop the interpreter. This may be fixed in a future version of boost.python.</strong></span> to stop the interpreter. This may be fixed in a future version of boost.python.</b></span>
</p></td></tr> </p></td></tr>
</table></div> </table></div>
<p> <p>
(Of course, there can be other C++ code between all of these steps.) (Of course, there can be other C++ code between all of these steps.)
</p> </p>
<div class="blockquote"><blockquote class="blockquote"><p> <div class="blockquote"><blockquote class="blockquote">
<span class="emphasis"><em><span class="bold"><strong>Now that we can embed the interpreter in <p>
our programs, lets see how to put it to use...</strong></span></em></span> </p>
</p></blockquote></div> <p>
<div class="section"> <span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
our programs, lets see how to put it to use...</b></span></em></span>
</p>
<p>
</p>
</blockquote></div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div> <a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
<p> <p>
As you probably already know, objects in Python are reference-counted. Naturally, As you probably already know, objects in Python are reference-counted. Naturally,
the <code class="literal">PyObject</code>s of the Python C API are also reference-counted. the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted.
There is a difference however. While the reference-counting is fully automatic There is a difference however. While the reference-counting is fully automatic
in Python, the Python C API requires you to do it <a href="http://www.python.org/doc/current/c-api/refcounting.html" target="_top">by in Python, the Python<span class="emphasis"><em>C API requires you to do it [@http:</em></span>/www.python.org/doc/current/api/refcounts.html
hand</a>. This is messy and especially hard to get right in the presence by hand]. This is messy and especially hard to get right in the presence
of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a> 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 and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
automate the process. automate the process.
</p> </p>
<a name="using_the_interpreter.running_python_code"></a><h3> <a name="using_the_interpreter.running_python_code"></a><h2>
<a name="id773549"></a> <a name="id471439"></a>
Running Python code Running Python code
</h3> </h2>
<p> <p>
Boost.python provides three related functions to run Python code from C++. Boost.python provides three related functions to run Python code from C++.
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">expression</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">expression</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
<span class="identifier">object</span> <span class="identifier">exec</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">code</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span> <span class="identifier">object</span> <span class="identifier">exec</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">code</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
<span class="identifier">object</span> <span class="identifier">exec_file</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">filename</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span> <span class="identifier">object</span> <span class="identifier">exec_file</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">filename</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
</pre> </pre>
@@ -149,26 +156,28 @@ exe embedded_program # name of the executable
and exec_file executes the code contained in the given file. and exec_file executes the code contained in the given file.
</p> </p>
<p> <p>
The <code class="literal">globals</code> and <code class="literal">locals</code> parameters are The <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters are
Python dictionaries containing the globals and locals of the context in which Python dictionaries containing the globals and locals of the context in which
to run the code. For most intents and purposes you can use the namespace to run the code. For most intents and purposes you can use the namespace
dictionary of the <code class="literal"><span class="underline">_main</span>_</code> dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
module for both parameters. module for both parameters.
</p> </p>
<p> <p>
Boost.python provides a function to import a module: Boost.python provides a function to import a module:
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">import</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">import</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
</pre> </pre>
<p> <p>
import imports a python module (potentially loading it into the running process import imports a python module (potentially loading it into the running process
first), and returns it. first), and returns it.
</p> </p>
<p> <p>
Let's import the <code class="literal"><span class="underline">_main</span>_</code> Let's import the <tt class="literal"><span class="underline">_main</span>_</tt>
module and run some Python code in its namespace: module and run some Python code in its namespace:
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</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">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</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">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"hello = file('hello.txt', 'w')\n"</span> <span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"hello = file('hello.txt', 'w')\n"</span>
@@ -180,40 +189,43 @@ exe embedded_program # name of the executable
This should create a file called 'hello.txt' in the current directory containing This should create a file called 'hello.txt' in the current directory containing
a phrase that is well-known in programming circles. a phrase that is well-known in programming circles.
</p> </p>
<a name="using_the_interpreter.manipulating_python_objects"></a><h3> <a name="using_the_interpreter.manipulating_python_objects"></a><h2>
<a name="id774064"></a> <a name="id472027"></a>
Manipulating Python objects Manipulating Python objects
</h3> </h2>
<p> <p>
Often we'd like to have a class to manipulate Python objects. But we have Often we'd like to have a class to manipulate Python objects. But we have
already seen such a class above, and in the <a href="object.html" target="_top">previous already seen such a class above, and in the <a href="object.html" target="_top">previous
section</a>: the aptly named <code class="literal">object</code> class and its section</a>: the aptly named <tt class="literal">object</tt> class and its
derivatives. We've already seen that they can be constructed from a <code class="literal">handle</code>. derivatives. We've already seen that they can be constructed from a <tt class="literal">handle</tt>.
The following examples should further illustrate this fact: The following examples should further illustrate this fact:
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</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">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</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">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"result = 5 ** 2"</span><span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">);</span> <span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"result = 5 ** 2"</span><span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">);</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">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</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">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
</pre> </pre>
<p> <p>
Here we create a dictionary object for the <code class="literal"><span class="underline">_main</span>_</code> Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
module's namespace. Then we assign 5 squared to the result variable and read module's namespace. Then we assign 5 squared to the result variable and read
this variable from the dictionary. Another way to achieve the same result this variable from the dictionary. Another way to achieve the same result
is to use eval instead, which returns the result directly: is to use eval instead, which returns the result directly:
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">);</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> <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>
</pre> </pre>
<a name="using_the_interpreter.exception_handling"></a><h3> <a name="using_the_interpreter.exception_handling"></a><h2>
<a name="id774390"></a> <a name="id472399"></a>
Exception handling Exception handling
</h3> </h2>
<p> <p>
If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a> If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>
is thrown: is thrown:
</p> </p>
<pre class="programlisting"><span class="keyword">try</span> <pre class="programlisting">
<span class="keyword">try</span>
<span class="special">{</span> <span class="special">{</span>
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5/0"</span><span class="special">);</span> <span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5/0"</span><span class="special">);</span>
<span class="comment">// execution will never get here: <span class="comment">// execution will never get here:
@@ -225,16 +237,17 @@ exe embedded_program # name of the executable
</span><span class="special">}</span> </span><span class="special">}</span>
</pre> </pre>
<p> <p>
The <code class="literal">error_already_set</code> exception class doesn't carry any The <tt class="literal">error_already_set</tt> exception class doesn't carry any
information in itself. To find out more about the Python exception that occurred, information in itself. To find out more about the Python exception that occurred,
you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
handling functions</a> of the Python C API in your catch-statement. This handling functions</a> of the Python<span class="emphasis"><em>C API in your catch-statement.
can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a> This can be as simple as calling [@http:</em></span>/www.python.org/doc/api/exceptionHandling.html#l2h-70
to print the exception's traceback to the console, or comparing the type PyErr_Print()] to print the exception's traceback to the console, or comparing
of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard the type of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
exceptions</a>: exceptions</a>:
</p> </p>
<pre class="programlisting"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&amp;)</span> <pre class="programlisting">
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&amp;)</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="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">{</span> <span class="special">{</span>
@@ -255,7 +268,7 @@ exe embedded_program # name of the executable
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -265,7 +278,7 @@ exe embedded_program # name of the executable
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Exception Translation</title> <title> Exception Translation</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="iterators.html" title="Iterators"> <link rel="prev" href="iterators.html" title="Iterators">
<link rel="next" href="techniques.html" title="General Techniques"> <link rel="next" href="techniques.html" title=" General Techniques">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.exception"></a> Exception Translation</h2></div></div></div> <a name="python.exception"></a> Exception Translation</h2></div></div></div>
<p> <p>
@@ -30,12 +30,14 @@
is the point where C++ meets Python. Boost.Python provides a default exception is the point where C++ meets Python. Boost.Python provides a default exception
handler that translates selected standard exceptions, then gives up: handler that translates selected standard exceptions, then gives up:
</p> </p>
<pre class="programlisting"><span class="keyword">raise</span> <span class="identifier">RuntimeError</span><span class="special">,</span> <span class="string">'unidentifiable C++ Exception'</span> <pre class="programlisting">
<span class="keyword">raise</span> <span class="identifier">RuntimeError</span><span class="special">,</span> <span class="string">'unidentifiable C++ Exception'</span>
</pre> </pre>
<p> <p>
Users may provide custom translation. Here's an example: Users may provide custom translation. Here's an example:
</p> </p>
<pre class="programlisting"><span class="identifier">struct</span> <span class="identifier">PodBayDoorException</span><span class="special">;</span> <pre class="programlisting">
<span class="identifier">struct</span> <span class="identifier">PodBayDoorException</span><span class="special">;</span>
<span class="identifier">void</span> <span class="identifier">translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span> <span class="identifier">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">void</span> <span class="identifier">translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span> <span class="identifier">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span> <span class="string">"I'm sorry Dave..."</span><span class="special">);</span> <span class="identifier">PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span> <span class="string">"I'm sorry Dave..."</span><span class="special">);</span>
<span class="special">}</span> <span class="special">}</span>
@@ -47,7 +49,7 @@
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -57,7 +59,7 @@
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Exposing Classes</title> <title> Exposing Classes</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="hello.html" title="Building Hello World"> <link rel="prev" href="hello.html" title=" Building Hello World">
<link rel="next" href="functions.html" title="Functions"> <link rel="next" href="functions.html" title="Functions">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.exposing"></a> Exposing Classes</h2></div></div></div> <a name="python.exposing"></a> Exposing Classes</h2></div></div></div>
<div class="toc"><dl> <div class="toc"><dl>
@@ -40,7 +40,8 @@
<p> <p>
Consider a C++ class/struct that we want to expose to Python: Consider a C++ class/struct that we want to expose to Python:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">World</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">void</span> <span class="identifier">set</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="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</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="keyword">void</span> <span class="identifier">set</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="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</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="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
@@ -50,7 +51,8 @@
<p> <p>
We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper: We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span> <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
@@ -62,29 +64,31 @@
<span class="special">}</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
Here, we wrote a C++ class wrapper that exposes the member functions <code class="literal">greet</code> Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
and <code class="literal">set</code>. Now, after building our module as a shared library, and <tt class="literal">set</tt>. Now, after building our module as a shared library,
we may use our class <code class="literal">World</code> in Python. Here's a sample Python we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
session: session:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span> <pre class="programlisting">
<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="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">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">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="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">'howdy'</span> <span class="string">'howdy'</span>
</pre> </pre>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.constructors"></a>Constructors</h3></div></div></div> <a name="python.constructors"></a>Constructors</h3></div></div></div>
<p> <p>
Our previous example didn't have any explicit constructors. Since <code class="literal">World</code> Our previous example didn't have any explicit constructors. Since <tt class="literal">World</tt>
is declared as a plain struct, it has an implicit default constructor. Boost.Python is declared as a plain struct, it has an implicit default constructor. Boost.Python
exposes the default constructor by default, which is why we were able to exposes the default constructor by default, which is why we were able to
write write
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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>
</pre> </pre>
<p> <p>
We may wish to wrap a class with a non-default constructor. Let us build We may wish to wrap a class with a non-default constructor. Let us build
@@ -92,7 +96,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">World</span>
<span class="special">{</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 <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
</span> <span class="keyword">void</span> <span class="identifier">set</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="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span> </span> <span class="keyword">void</span> <span class="identifier">set</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="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
@@ -101,12 +106,13 @@
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
This time <code class="literal">World</code> has no default constructor; our previous This time <tt class="literal">World</tt> has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose it. wrapping code would fail to compile when the library tried to expose it.
We have to tell <code class="literal">class_&lt;World&gt;</code> about the constructor We have to tell <tt class="literal">class_&lt;World&gt;</tt> about the constructor
we want to expose instead. we want to expose instead.
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span> <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
@@ -118,16 +124,17 @@
<span class="special">}</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
<code class="literal">init&lt;std::string&gt;()</code> exposes the constructor taking <tt class="literal">init&lt;std::string&gt;()</tt> exposes the constructor taking
in a <code class="literal">std::string</code> (in Python, constructors are spelled in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
"<code class="literal">"<span class="underline">_init</span>_"</code>"). "<tt class="literal">"<span class="underline">_init</span>_"</tt>").
</p> </p>
<p> <p>
We can expose additional constructors by passing more <code class="literal">init&lt;...&gt;</code>s We can expose additional constructors by passing more <tt class="literal">init&lt;...&gt;</tt>s
to the <code class="literal">def()</code> member function. Say for example we have to the <tt class="literal">def()</tt> member function. Say for example we have
another World constructor taking in two doubles: another World constructor taking in two doubles:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
@@ -135,25 +142,27 @@
</pre> </pre>
<p> <p>
On the other hand, if we do not wish to expose any constructors at all, we On the other hand, if we do not wish to expose any constructors at all, we
may use <code class="literal">no_init</code> instead: may use <tt class="literal">no_init</tt> instead:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
</pre> </pre>
<p> <p>
This actually adds an <code class="literal"><span class="underline">_init</span>_</code> This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
method which always raises a Python RuntimeError exception. method which always raises a Python RuntimeError exception.
</p> </p>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div> <a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
<p> <p>
Data members may also be exposed to Python so that they can be accessed as Data members may also be exposed to Python so that they can be accessed as
attributes of the corresponding Python class. Each data member that we wish attributes of the corresponding Python class. Each data member that we wish
to be exposed may be regarded as <span class="bold"><strong>read-only</strong></span> to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
or <span class="bold"><strong>read-write</strong></span>. Consider this class <code class="literal">Var</code>: or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Var</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Var</span>
<span class="special">{</span> <span class="special">{</span>
<span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span> <span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span>
@@ -161,10 +170,11 @@
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
Our C++ <code class="literal">Var</code> class and its data members can be exposed Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
to Python: to Python:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span> <span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span>
</pre> </pre>
@@ -174,22 +184,24 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">&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="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="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> <span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
</pre> </pre>
<p> <p>
Note that <code class="literal">name</code> is exposed as <span class="bold"><strong>read-only</strong></span> Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
while <code class="literal">value</code> is exposed as <span class="bold"><strong>read-write</strong></span>. while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
</p> </p>
<pre class="programlisting"><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 <pre class="programlisting">
<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><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="error">?</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="error">'</span><span class="identifier">t</span> <span class="identifier">set</span> <span class="identifier">attribute</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>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_properties"></a>Class Properties</h3></div></div></div> <a name="python.class_properties"></a>Class Properties</h3></div></div></div>
<p> <p>
@@ -200,7 +212,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Num</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Num</span>
<span class="special">{</span> <span class="special">{</span>
<span class="identifier">Num</span><span class="special">();</span> <span class="identifier">Num</span><span class="special">();</span>
<span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
@@ -211,10 +224,11 @@
<p> <p>
However, in Python attribute access is fine; it doesn't neccessarily break However, in Python attribute access is fine; it doesn't neccessarily break
encapsulation to let users handle attributes directly, because the attributes encapsulation to let users handle attributes directly, because the attributes
can just be a different syntax for a method call. Wrapping our <code class="literal">Num</code> can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
class using Boost.Python: class using Boost.Python:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span>
<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> <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>
<span class="special">.</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> <span class="special">.</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>
</pre> </pre>
@@ -223,23 +237,25 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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">&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">(</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 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></pre> </span></pre>
<p> <p>
Take note that the class property <code class="literal">rovalue</code> is exposed as Take note that the class property <tt class="literal">rovalue</tt> is exposed as
<span class="bold"><strong>read-only</strong></span> since the <code class="literal">rovalue</code> <span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
setter member function is not passed in: setter member function is not passed in:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.inheritance"></a>Inheritance</h3></div></div></div> <a name="python.inheritance"></a>Inheritance</h3></div></div></div>
<p> <p>
@@ -252,78 +268,85 @@
<p> <p>
Consider this trivial inheritance structure: Consider this trivial inheritance structure:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span> <span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
</pre> </pre>
<p> <p>
And a set of C++ functions operating on <code class="literal">Base</code> and <code class="literal">Derived</code> And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
object instances: object instances:
</p> </p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span> <pre class="programlisting">
<span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span>
<span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span> <span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span>
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span> <span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
We've seen how we can wrap the base class <code class="literal">Base</code>: We've seen how we can wrap the base class <tt class="literal">Base</tt>:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="comment">/*...*/</span> <span class="comment">/*...*/</span>
<span class="special">;</span> <span class="special">;</span>
</pre> </pre>
<p> <p>
Now we can inform Boost.Python of the inheritance relationship between <code class="literal">Derived</code> Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
and its base class <code class="literal">Base</code>. Thus: and its base class <tt class="literal">Base</tt>. Thus:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span>
<span class="comment">/*...*/</span> <span class="comment">/*...*/</span>
<span class="special">;</span> <span class="special">;</span>
</pre> </pre>
<p> <p>
Doing so, we get some things for free: Doing so, we get some things for free:
</p> </p>
<div class="orderedlist"><ol class="orderedlist" type="1"> <div class="orderedlist"><ol type="1">
<li class="listitem"> <li>
Derived automatically inherits all of Base's Python methods (wrapped Derived automatically inherits all of Base's Python methods (wrapped C++
C++ member functions) member functions)
</li> </li>
<li class="listitem"> <li>
<span class="bold"><strong>If</strong></span> Base is polymorphic, <code class="literal">Derived</code> <span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
objects which have been passed to Python via a pointer or reference to objects which have been passed to Python via a pointer or reference to
<code class="literal">Base</code> can be passed where a pointer or reference to <tt class="literal">Base</tt> can be passed where a pointer or reference to
<code class="literal">Derived</code> is expected. <tt class="literal">Derived</tt> is expected.
</li> </li>
</ol></div> </ol></div>
<p> <p>
Now, we will expose the C++ free functions <code class="literal">b</code> and <code class="literal">d</code> Now, we will expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
and <code class="literal">factory</code>: and <tt class="literal">factory</tt>:
</p> </p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
</pre> </pre>
<p> <p>
Note that free function <code class="literal">factory</code> is being used to generate Note that free function <tt class="literal">factory</tt> is being used to generate
new instances of class <code class="literal">Derived</code>. In such cases, we use new instances of class <tt class="literal">Derived</tt>. In such cases, we use
<code class="literal">return_value_policy&lt;manage_new_object&gt;</code> to instruct <tt class="literal">return_value_policy&lt;manage_new_object&gt;</tt> to instruct
Python to adopt the pointer to <code class="literal">Base</code> and hold the instance Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
in a new Python <code class="literal">Base</code> object until the the Python object in a new Python <tt class="literal">Base</tt> object until the the Python object
is destroyed. We will see more of Boost.Python <a class="link" href="functions.html#python.call_policies" title="Call Policies">call is destroyed. We will see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
policies</a> later. policies</a> later.
</p> </p>
<pre class="programlisting"><span class="comment">// Tell Python to take ownership of factory's result <pre class="programlisting">
<span class="comment">// Tell Python to take ownership of factory's result
</span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span> </span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span>
<span class="identifier">return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span> <span class="identifier">return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div> <a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
<p> <p>
In this section, we will learn how to make functions behave polymorphically In this section, we will learn how to make functions behave polymorphically
through virtual functions. Continuing our example, let us add a virtual function through virtual functions. Continuing our example, let us add a virtual function
to our <code class="literal">Base</code> class: to our <tt class="literal">Base</tt> class:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
@@ -333,15 +356,16 @@
One of the goals of Boost.Python is to be minimally intrusive on an existing One of the goals of Boost.Python is to be minimally intrusive on an existing
C++ design. In principle, it should be possible to expose the interface for C++ design. In principle, it should be possible to expose the interface for
a 3rd party library without changing it. It is not ideal to add anything a 3rd party library without changing it. It is not ideal to add anything
to our class <code class="computeroutput"><span class="identifier">Base</span></code>. Yet, when to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
you have a virtual function that's going to be overridden in Python and called you have a virtual function that's going to be overridden in Python and called
polymorphically <span class="bold"><strong>from C++</strong></span>, we'll need to polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
add some scaffoldings to make things work properly. What we'll do is write add some scaffoldings to make things work properly. What we'll do is write
a class wrapper that derives from <code class="computeroutput"><span class="identifier">Base</span></code> a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
that will unintrusively hook into the virtual functions so that a Python that will unintrusively hook into the virtual functions so that a Python
override may be called: override may be called:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
<span class="special">{</span> <span class="special">{</span>
@@ -350,79 +374,81 @@
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
Notice too that in addition to inheriting from <code class="computeroutput"><span class="identifier">Base</span></code>, Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
we also multiply- inherited <code class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></code> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>). we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
The <code class="computeroutput"><span class="identifier">wrapper</span></code> template makes The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
the job of wrapping classes that are meant to overridden in Python, easier. the job of wrapping classes that are meant to overridden in Python, easier.
</p> </p>
<div class="sidebar"> <div class="sidebar">
<p class="title"><b></b></p>
<p> <p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
</p> </p>
<p> <p>
If you are using Microsoft Visual C++ 6 or 7, you have to write <code class="computeroutput"><span class="identifier">f</span></code> as: 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>
<code 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></code>. <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>.
</p> </p>
</div> </div>
<p> <p>
BaseWrap's overridden virtual member function <code class="computeroutput"><span class="identifier">f</span></code> BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
in effect calls the corresponding method of the Python object through <code class="computeroutput"><span class="identifier">get_override</span></code>. in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
</p> </p>
<p> <p>
Finally, exposing <code class="computeroutput"><span class="identifier">Base</span></code>: Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span>
<span class="special">;</span> <span class="special">;</span>
</pre> </pre>
<p> <p>
<code class="computeroutput"><span class="identifier">pure_virtual</span></code> signals Boost.Python <tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
that the function <code class="computeroutput"><span class="identifier">f</span></code> is a that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
pure virtual function. pure virtual function.
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"> <tr><td colspan="2" align="left" valign="top">
<p> <p>
<span class="bold"><strong>member function and methods</strong></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"><strong>methods</strong></span>. 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"><strong>member functions</strong></span> Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
</p> </p>
</td></tr> </td></tr>
</table></div> </table></div>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div> <a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
<p> <p>
We've seen in the previous section how classes with pure virtual functions 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 are wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class
wrapper</a> facilities. If we wish to wrap <span class="bold"><strong>non</strong></span>-pure-virtual 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. functions instead, the mechanism is a bit different.
</p> </p>
<p> <p>
Recall that in the <a class="link" href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous
section</a>, we wrapped a class with a pure virtual function that we then section</a>, we wrapped a class with a pure virtual function that we then
implemented in C++, or Python classes derived from it. Our base class: implemented in C++, or Python classes derived from it. Our base class:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
had a pure virtual function <code class="literal">f</code>. If, however, its member had a pure virtual function <tt class="literal">f</tt>. If, however, its member
function <code class="literal">f</code> was not declared as pure virtual: function <tt class="literal">f</tt> was not declared as pure virtual:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Base</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span> <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span>
@@ -431,7 +457,8 @@
<p> <p>
We wrap it this way: We wrap it this way:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
<span class="special">{</span> <span class="special">{</span>
@@ -444,42 +471,43 @@
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
Notice how we implemented <code class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></code>. Now, Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
we have to check if there is an override for <code class="computeroutput"><span class="identifier">f</span></code>. we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
If none, then we call <code class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></code>. 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> </p>
<div class="sidebar"> <div class="sidebar">
<p class="title"><b></b></p>
<p> <p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
</p> </p>
<p> <p>
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
with the <code class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></code> as: with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:
</p> </p>
<p> <p>
<code 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></code>. <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>.
</p> </p>
</div> </div>
<p> <p>
Finally, exposing: Finally, exposing:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span>
<span class="special">;</span> <span class="special">;</span>
</pre> </pre>
<p> <p>
Take note that we expose both <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></code>. Boost.Python needs to keep track Take note that we expose both <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
of 1) the dispatch function <code class="literal">f</code> and 2) the forwarding function of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
to its default implementation <code class="literal">default_f</code>. There's a special to its default implementation <tt class="literal">default_f</tt>. There's a special
<code class="literal">def</code> function for this purpose. <tt class="literal">def</tt> function for this purpose.
</p> </p>
<p> <p>
In Python, the results would be as expected: In Python, the results would be as expected:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">&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="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="keyword">return</span> <span class="number">42</span> <span class="special">...</span> <span class="keyword">return</span> <span class="number">42</span>
@@ -487,37 +515,40 @@
<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> <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>
</pre> </pre>
<p> <p>
Calling <code class="literal">base.f()</code>: Calling <tt class="literal">base.f()</tt>:
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">0</span> <span class="number">0</span>
</pre> </pre>
<p> <p>
Calling <code class="literal">derived.f()</code>: Calling <tt class="literal">derived.f()</tt>:
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">42</span> <span class="number">42</span>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <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="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
<a name="class_operators_special_functions.python_operators"></a><h3> <a name="class_operators_special_functions.python_operators"></a><h2>
<a name="id764956"></a> <a name="id461460"></a>
Python Operators Python Operators
</h3> </h2>
<p> <p>
C is well known for the abundance of operators. C++ extends this to the extremes C is well known for the abundance of operators. C++ extends this to the extremes
by allowing operator overloading. Boost.Python takes advantage of this and by allowing operator overloading. Boost.Python takes advantage of this and
makes it easy to wrap C++ operator-powered classes. makes it easy to wrap C++ operator-powered classes.
</p> </p>
<p> <p>
Consider a file position class <code class="literal">FilePos</code> and a set of operators Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
that take on FilePos instances: that take on FilePos instances:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">FilePos</span> <span class="special">{</span> <span class="comment">/*...*/</span> <span class="special">};</span> <pre class="programlisting">
<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">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">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span> <span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
@@ -531,7 +562,8 @@
The class and the various operators can be mapped to Python rather easily The class and the various operators can be mapped to Python rather easily
and intuitively: and intuitively:
</p> </p>
<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __add__ <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __add__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __radd__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __radd__
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __sub__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __sub__
@@ -543,16 +575,16 @@
<p> <p>
The code snippet above is very clear and needs almost no explanation at all. The code snippet above is very clear and needs almost no explanation at all.
It is virtually the same as the operators' signatures. Just take note that It is virtually the same as the operators' signatures. Just take note that
<code class="literal">self</code> refers to FilePos object. Also, not every class <tt class="literal">self</tt> refers to FilePos object. Also, not every class
<code class="literal">T</code> that you might need to interact with in an operator <tt class="literal">T</tt> that you might need to interact with in an operator
expression is (cheaply) default-constructible. You can use <code class="literal">other&lt;T&gt;()</code> expression is (cheaply) default-constructible. You can use <tt class="literal">other&lt;T&gt;()</tt>
in place of an actual <code class="literal">T</code> instance when writing "self in place of an actual <tt class="literal">T</tt> instance when writing "self
expressions". expressions".
</p> </p>
<a name="class_operators_special_functions.special_methods"></a><h3> <a name="class_operators_special_functions.special_methods"></a><h2>
<a name="id765570"></a> <a name="id462216"></a>
Special Methods Special Methods
</h3> </h2>
<p> <p>
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python 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 supports all of the standard special method names supported by real Python
@@ -560,7 +592,8 @@
wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>. wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>.
Example: Example:
</p> </p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">Rational</span> <pre class="programlisting">
<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="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">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">pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span> <span class="identifier">Rational</span><span class="special">);</span>
@@ -579,19 +612,19 @@
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"><p> <tr><td colspan="2" align="left" valign="top"><p>
What is the business of <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>? Well, the method <code class="computeroutput"><span class="identifier">str</span></code> requires the <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code> 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 <code 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></code>. 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>.
</p></td></tr> </p></td></tr>
</table></div> </table></div>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -601,7 +634,7 @@
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Functions</title> <title>Functions</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="exposing.html" title="Exposing Classes"> <link rel="prev" href="exposing.html" title=" Exposing Classes">
<link rel="next" href="object.html" title="Object Interface"> <link rel="next" href="object.html" title=" Object Interface">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.functions"></a>Functions</h2></div></div></div> <a name="python.functions"></a>Functions</h2></div></div></div>
<div class="toc"><dl> <div class="toc"><dl>
@@ -38,12 +38,18 @@
facilities that will make it even easier for us to expose C++ functions that facilities that will make it even easier for us to expose C++ functions that
take advantage of C++ features such as overloading and default arguments. take advantage of C++ features such as overloading and default arguments.
</p> </p>
<div class="blockquote"><blockquote class="blockquote"><p> <div class="blockquote"><blockquote class="blockquote">
<span class="emphasis"><em>Read on...</em></span> <p>
</p></blockquote></div> </p>
<p>
<span class="emphasis"><em>Read on...</em></span>
</p>
<p>
</p>
</blockquote></div>
<p> <p>
But before you do, you might want to fire up Python 2.2 or later and type But before you do, you might want to fire up Python 2.2 or later and type
<code class="literal">&gt;&gt;&gt; import this</code>. <tt class="literal">&gt;&gt;&gt; import this</tt>.
</p> </p>
<pre class="programlisting">&gt;&gt;&gt; import this <pre class="programlisting">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters The Zen of Python, by Tim Peters
@@ -62,12 +68,12 @@ In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it 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. Although that way may not be obvious at first unless you're Dutch.
Now is better than never. Now is better than never.
Although never is often better than <span class="bold"><strong>right</strong></span> now. 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 hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good 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! Namespaces are one honking great idea -- let's do more of those!
</pre> </pre>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.call_policies"></a>Call Policies</h3></div></div></div> <a name="python.call_policies"></a>Call Policies</h3></div></div></div>
<p> <p>
@@ -81,14 +87,16 @@ Namespaces are one honking great idea -- let's do more of those!
so Boost.Python must deal with them. To do this, it may need your help. Consider so Boost.Python must deal with them. To do this, it may need your help. Consider
the following C++ function: the following C++ function:
</p> </p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span>
</pre> </pre>
<p> <p>
How should the library wrap this function? A naive approach builds a Python How should the library wrap this function? A naive approach builds a Python
X object around result reference. This strategy might or might not work out. X object around result reference. This strategy might or might not work out.
Here's an example where it didn't Here's an example where it didn't
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</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="preprocessor"># x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</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="preprocessor"># x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">y</span> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">y</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
</pre> </pre>
@@ -98,7 +106,8 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
Well, what if f() was implemented as shown below: Well, what if f() was implemented as shown below:
</p> </p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</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="special">{</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">z</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">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span> <span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
@@ -115,30 +124,29 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
Here's what's happening: Here's what's happening:
</p> </p>
<div class="orderedlist"><ol class="orderedlist" type="1"> <div class="orderedlist"><ol type="1">
<li class="listitem"> <li>
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code> <tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
and a pointer to <code class="literal">z</code> and a pointer to <tt class="literal">z</tt>
</li> </li>
<li class="listitem"> <li>
A reference to <code class="literal">y.x</code> is returned A reference to <tt class="literal">y.x</tt> is returned
</li> </li>
<li class="listitem"> <li>
<code class="literal">y</code> is deleted. <code class="literal">x</code> is a dangling reference <tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
</li> </li>
<li class="listitem"> <li>
<code class="literal">x.some_method()</code> is called <tt class="literal">x.some_method()</tt> is called
</li> </li>
<li class="listitem"> <li><span class="bold"><b>BOOM!</b></span></li>
<span class="bold"><strong>BOOM!</strong></span>
</li>
</ol></div> </ol></div>
<p> <p>
We could copy result into a new object: We could copy result into a new object:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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 <pre class="programlisting">
<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="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> </span><span class="number">3.14</span>
</pre> </pre>
@@ -152,24 +160,27 @@ Namespaces are one honking great idea -- let's do more of those!
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Y</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Y</span>
<span class="special">{</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="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">int</span> <span class="identifier">z_value</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">z</span><span class="special">-&gt;</span><span class="identifier">value</span><span class="special">();</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">z_value</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">z</span><span class="special">-&gt;</span><span class="identifier">value</span><span class="special">();</span> <span class="special">}</span>
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
Notice that the data member <code class="literal">z</code> is held by class Y using Notice that the data member <tt class="literal">z</tt> is held by class Y using
a raw pointer. Now we have a potential dangling pointer problem inside Y: a raw pointer. Now we have a potential dangling pointer problem inside Y:
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</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="preprocessor"># y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</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="preprocessor"># y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">z</span> <span class="preprocessor"># Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">z</span> <span class="preprocessor"># Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
</pre> </pre>
<p> <p>
For reference, here's the implementation of <code class="literal">f</code> again: For reference, here's the implementation of <tt class="literal">f</tt> again:
</p> </p>
<pre class="programlisting"><span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</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="special">{</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">z</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">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span> <span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
@@ -178,70 +189,71 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
Here's what's happening: Here's what's happening:
</p> </p>
<div class="orderedlist"><ol class="orderedlist" type="1"> <div class="orderedlist"><ol type="1">
<li class="listitem"> <li>
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code> <tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
and a pointer to <code class="literal">z</code> and a pointer to <tt class="literal">z</tt>
</li> </li>
<li class="listitem"> <li>
A pointer to <code class="literal">z</code> is held by <code class="literal">y</code> A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
</li> </li>
<li class="listitem"> <li>
A reference to <code class="literal">y.x</code> is returned A reference to <tt class="literal">y.x</tt> is returned
</li> </li>
<li class="listitem"> <li>
<code class="literal">z</code> is deleted. <code class="literal">y.z</code> is a dangling <tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
pointer </li>
</li> <li>
<li class="listitem"> <tt class="literal">y.z_value()</tt> is called
<code class="literal">y.z_value()</code> is called </li>
</li> <li>
<li class="listitem"> <tt class="literal">z-&gt;value()</tt> is called
<code class="literal">z-&gt;value()</code> is called </li>
</li> <li><span class="bold"><b>BOOM!</b></span></li>
<li class="listitem">
<span class="bold"><strong>BOOM!</strong></span>
</li>
</ol></div> </ol></div>
<a name="call_policies.call_policies"></a><h3> <a name="call_policies.call_policies"></a><h2>
<a name="id767074"></a> <a name="id464076"></a>
Call Policies Call Policies
</h3> </h2>
<p> <p>
Call Policies may be used in situations such as the example detailed above. Call Policies may be used in situations such as the example detailed above.
In our example, <code class="literal">return_internal_reference</code> and <code class="literal">with_custodian_and_ward</code> In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
are our friends: are our friends:
</p> </p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <pre class="programlisting">
<span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span>
<span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span>
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="special">&gt;());</span> <span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
</pre> </pre>
<p> <p>
What are the <code class="literal">1</code> and <code class="literal">2</code> parameters, you What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
ask? ask?
</p> </p>
<pre class="programlisting"><span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span> <pre class="programlisting">
<span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span>
</pre> </pre>
<p> <p>
Informs Boost.Python that the first argument, in our case <code class="literal">Y&amp; Informs Boost.Python that the first argument, in our case <tt class="literal">Y&amp;
y</code>, is the owner of the returned reference: <code class="literal">X&amp;</code>. y</tt>, is the owner of the returned reference: <tt class="literal">X&amp;</tt>.
The "<code class="literal">1</code>" simply specifies the first argument. The "<tt class="literal">1</tt>" simply specifies the first argument.
In short: "return an internal reference <code class="literal">X&amp;</code> owned In short: "return an internal reference <tt class="literal">X&amp;</tt> owned
by the 1st argument <code class="literal">Y&amp; y</code>". by the 1st argument <tt class="literal">Y&amp; y</tt>".
</p> </p>
<pre class="programlisting"><span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <pre class="programlisting">
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>
</pre> </pre>
<p> <p>
Informs Boost.Python that the lifetime of the argument indicated by ward Informs Boost.Python that the lifetime of the argument indicated by ward
(i.e. the 2nd argument: <code class="literal">Z* z</code>) is dependent on the lifetime (i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
of the argument indicated by custodian (i.e. the 1st argument: <code class="literal">Y&amp; of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&amp;
y</code>). y</tt>).
</p> </p>
<p> <p>
It is also important to note that we have defined two policies above. Two It is also important to note that we have defined two policies above. Two
or more policies can be composed by chaining. Here's the general syntax: or more policies can be composed by chaining. Here's the general syntax:
</p> </p>
<pre class="programlisting"><span class="identifier">policy1</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span> <pre class="programlisting">
<span class="identifier">policy1</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy2</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span> <span class="identifier">policy2</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy3</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">policy3</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
</pre> </pre>
@@ -249,44 +261,42 @@ Namespaces are one honking great idea -- let's do more of those!
Here is the list of predefined call policies. A complete reference detailing Here is the list of predefined call policies. A complete reference detailing
these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>. these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
<span class="bold"><strong>with_custodian_and_ward</strong></span>: Ties lifetimes <span class="bold"><b>with_custodian_and_ward</b></span>: Ties lifetimes
of the arguments of the arguments
</li> </li>
<li class="listitem"> <li>
<span class="bold"><strong>with_custodian_and_ward_postcall</strong></span>: Ties <span class="bold"><b>with_custodian_and_ward_postcall</b></span>: Ties
lifetimes of the arguments and results lifetimes of the arguments and results
</li> </li>
<li class="listitem"> <li>
<span class="bold"><strong>return_internal_reference</strong></span>: Ties lifetime <span class="bold"><b>return_internal_reference</b></span>: Ties lifetime
of one argument to that of result of one argument to that of result
</li> </li>
<li class="listitem"> <li>
<span class="bold"><strong>return_value_policy&lt;T&gt; with T one of:</strong></span> <span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><div class="itemizedlist"><ul type="circle">
<div class="itemizedlist"><ul class="itemizedlist" type="circle"> <li>
<li class="listitem"> <span class="bold"><b>reference_existing_object</b></span>: naive (dangerous)
<span class="bold"><strong>reference_existing_object</strong></span>: naive approach
(dangerous) approach </li>
</li> <li>
<li class="listitem"> <span class="bold"><b>copy_const_reference</b></span>: Boost.Python
<span class="bold"><strong>copy_const_reference</strong></span>: Boost.Python v1 approach
v1 approach </li>
</li> <li>
<li class="listitem"> <span class="bold"><b>copy_non_const_reference</b></span>:
<span class="bold"><strong>copy_non_const_reference</strong></span>: </li>
</li> <li>
<li class="listitem"> <span class="bold"><b>manage_new_object</b></span>: Adopt a pointer
<span class="bold"><strong>manage_new_object</strong></span>: Adopt a pointer and hold the instance
and hold the instance </li>
</li>
</ul></div> </ul></div>
</li> </li>
</ul></div> </ul></div>
<div class="sidebar"> <div class="sidebar">
<p class="title"><b></b></p>
<p> <p>
<span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><strong>Remember the Zen, Luke:</strong></span> <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span>
</p> </p>
<p> <p>
"Explicit is better than implicit" "Explicit is better than implicit"
@@ -296,7 +306,7 @@ Namespaces are one honking great idea -- let's do more of those!
</p> </p>
</div> </div>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.overloading"></a>Overloading</h3></div></div></div> <a name="python.overloading"></a>Overloading</h3></div></div></div>
<p> <p>
@@ -307,7 +317,8 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
We have here our C++ class: We have here our C++ class:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">X</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">)</span> <span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">)</span>
<span class="special">{</span> <span class="special">{</span>
@@ -334,7 +345,8 @@ Namespaces are one honking great idea -- let's do more of those!
Class X has 4 overloaded functions. We will start by introducing some member Class X has 4 overloaded functions. We will start by introducing some member
function pointer variables: function pointer variables:
</p> </p>
<pre class="programlisting"><span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <pre class="programlisting">
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
@@ -342,40 +354,45 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
With these in hand, we can proceed to define and wrap this for Python: With these in hand, we can proceed to define and wrap this for Python:
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">)</span> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx3</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx3</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx4</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx4</span><span class="special">)</span>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div> <a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
<p> <p>
Boost.Python wraps (member) function pointers. Unfortunately, C++ function Boost.Python wraps (member) function pointers. Unfortunately, C++ function
pointers carry no default argument info. Take a function <code class="literal">f</code> pointers carry no default argument info. Take a function <tt class="literal">f</tt>
with default arguments: with default arguments:
</p> </p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span> <pre class="programlisting">
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
</pre> </pre>
<p> <p>
But the type of a pointer to the function <code class="literal">f</code> has no information But the type of a pointer to the function <tt class="literal">f</tt> has no information
about its default arguments: about its default arguments:
</p> </p>
<pre class="programlisting"><span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost! <pre class="programlisting">
<span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
</span></pre> </span></pre>
<p> <p>
When we pass this function pointer to the <code class="literal">def</code> function, When we pass this function pointer to the <tt class="literal">def</tt> function,
there is no way to retrieve the default arguments: there is no way to retrieve the default arguments:
</p> </p>
<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// defaults lost! <pre class="programlisting">
<span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// defaults lost!
</span></pre> </span></pre>
<p> <p>
Because of this, when wrapping C++ code, we had to resort to manual wrapping Because of this, when wrapping C++ code, we had to resort to manual wrapping
as outlined in the <a class="link" href="functions.html#python.overloading" title="Overloading">previous section</a>, as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>,
or writing thin wrappers: or writing thin wrappers:
</p> </p>
<pre class="programlisting"><span class="comment">// write "thin wrappers" <pre class="programlisting">
<span class="comment">// write "thin wrappers"
</span><span class="keyword">int</span> <span class="identifier">f1</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span> </span><span class="keyword">int</span> <span class="identifier">f1</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">f2</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span> <span class="special">}</span> <span class="keyword">int</span> <span class="identifier">f2</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span> <span class="special">}</span>
@@ -389,22 +406,23 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
When you want to wrap functions (or member functions) that either: When you want to wrap functions (or member functions) that either:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
have default arguments, or have default arguments, or
</li> </li>
<li class="listitem"> <li>
are overloaded with a common sequence of initial arguments are overloaded with a common sequence of initial arguments
</li> </li>
</ul></div> </ul></div>
<a name="default_arguments.boost_python_function_overloads"></a><h3> <a name="default_arguments.boost_python_function_overloads"></a><h2>
<a name="id769042"></a> <a name="id466117"></a>
BOOST_PYTHON_FUNCTION_OVERLOADS BOOST_PYTHON_FUNCTION_OVERLOADS
</h3> </h2>
<p> <p>
Boost.Python now has a way to make it easier. For instance, given a function: Boost.Python now has a way to make it easier. For instance, given a function:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">{</span> <span class="special">{</span>
<span class="comment">/*...*/</span> <span class="comment">/*...*/</span>
<span class="special">}</span> <span class="special">}</span>
@@ -412,22 +430,24 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
The macro invocation: The macro invocation:
</p> </p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre> </pre>
<p> <p>
will automatically create the thin wrappers for us. This macro will create will automatically create the thin wrappers for us. This macro will create
a class <code class="literal">foo_overloads</code> that can be passed on to <code class="literal">def(...)</code>. a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
The third and fourth macro argument are the minimum arguments and maximum The third and fourth macro argument are the minimum arguments and maximum
arguments, respectively. In our <code class="literal">foo</code> function the minimum arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
number of arguments is 1 and the maximum number of arguments is 4. The <code class="literal">def(...)</code> number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
function will automatically add all the foo variants for us: function will automatically add all the foo variants for us:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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>
</pre> </pre>
<a name="default_arguments.boost_python_member_function_overloads"></a><h3> <a name="default_arguments.boost_python_member_function_overloads"></a><h2>
<a name="id769301"></a> <a name="id466436"></a>
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
</h3> </h2>
<p> <p>
Objects here, objects there, objects here there everywhere. More frequently Objects here, objects there, objects here there everywhere. More frequently
than anything else, we need to expose member functions of our classes to than anything else, we need to expose member functions of our classes to
@@ -436,11 +456,12 @@ Namespaces are one honking great idea -- let's do more of those!
play. Another macro is provided to make this a breeze. play. Another macro is provided to make this a breeze.
</p> </p>
<p> <p>
Like <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>, <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
may be used to automatically create the thin wrappers for wrapping member may be used to automatically create the thin wrappers for wrapping member
functions. Let's have an example: functions. Let's have an example:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">george</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">george</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">void</span> <span class="keyword">void</span>
<span class="identifier">wack_em</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">=</span> <span class="char">'x'</span><span class="special">)</span> <span class="identifier">wack_em</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">=</span> <span class="char">'x'</span><span class="special">)</span>
@@ -452,31 +473,34 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
The macro invocation: The macro invocation:
</p> </p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
</pre> </pre>
<p> <p>
will generate a set of thin wrappers for george's <code class="literal">wack_em</code> will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e. member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
the third and fourth macro argument). The thin wrappers are all enclosed the third and fourth macro argument). The thin wrappers are all enclosed
in a class named <code class="literal">george_overloads</code> that can then be used in a class named <tt class="literal">george_overloads</tt> that can then be used
as an argument to <code class="literal">def(...)</code>: as an argument to <tt class="literal">def(...)</tt>:
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
</pre> </pre>
<p> <p>
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
reference</a> for details. reference</a> for details.
</p> </p>
<a name="default_arguments.init_and_optional"></a><h3> <a name="default_arguments.init_and_optional"></a><h2>
<a name="id769596"></a> <a name="id466799"></a>
init and optional init and optional
</h3> </h2>
<p> <p>
A similar facility is provided for class constructors, again, with default A similar facility is provided for class constructors, again, with default
arguments or a sequence of overloads. Remember <code class="literal">init&lt;...&gt;</code>? arguments or a sequence of overloads. Remember <tt class="literal">init&lt;...&gt;</tt>?
For example, given a class X with a constructor: For example, given a class X with a constructor:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">X</span>
<span class="special">{</span> <span class="special">{</span>
<span class="identifier">X</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="char">'D'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">c</span> <span class="special">=</span> <span class="string">"constructor"</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">0.0</span><span class="special">);</span> <span class="identifier">X</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="char">'D'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">c</span> <span class="special">=</span> <span class="string">"constructor"</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">0.0</span><span class="special">);</span>
<span class="comment">/*...*/</span> <span class="comment">/*...*/</span>
@@ -485,23 +509,25 @@ Namespaces are one honking great idea -- let's do more of those!
<p> <p>
You can easily add this constructor to Boost.Python in one shot: You can easily add this constructor to Boost.Python in one shot:
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;())</span> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre> </pre>
<p> <p>
Notice the use of <code class="literal">init&lt;...&gt;</code> and <code class="literal">optional&lt;...&gt;</code> Notice the use of <tt class="literal">init&lt;...&gt;</tt> and <tt class="literal">optional&lt;...&gt;</tt>
to signify the default (optional arguments). to signify the default (optional arguments).
</p> </p>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div> <a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
<p> <p>
It was mentioned in passing in the previous section that <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code> It was mentioned in passing in the previous section that <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
and <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> can also be and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> can also be
used for overloaded functions and member functions with a common sequence used for overloaded functions and member functions with a common sequence
of initial arguments. Here is an example: of initial arguments. Here is an example:
</p> </p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span> <pre class="programlisting">
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
<span class="special">{</span> <span class="special">{</span>
<span class="comment">/*...*/</span> <span class="comment">/*...*/</span>
<span class="special">}</span> <span class="special">}</span>
@@ -525,56 +551,61 @@ Namespaces are one honking great idea -- let's do more of those!
Like in the previous section, we can generate thin wrappers for these overloaded Like in the previous section, we can generate thin wrappers for these overloaded
functions in one-shot: functions in one-shot:
</p> </p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
</pre> </pre>
<p> <p>
Then... Then...
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="special">(</span><span class="keyword">void</span><span class="special">(*)(</span><span class="keyword">bool</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">))</span><span class="number">0</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="special">(</span><span class="keyword">void</span><span class="special">(*)(</span><span class="keyword">bool</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">char</span><span class="special">))</span><span class="number">0</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
</pre> </pre>
<p> <p>
Notice though that we have a situation now where we have a minimum of zero Notice though that we have a situation now where we have a minimum of zero
(0) arguments and a maximum of 3 arguments. (0) arguments and a maximum of 3 arguments.
</p> </p>
<a name="auto_overloading.manual_wrapping"></a><h3> <a name="auto_overloading.manual_wrapping"></a><h2>
<a name="id770226"></a> <a name="id467581"></a>
Manual Wrapping Manual Wrapping
</h3> </h2>
<p> <p>
It is important to emphasize however that <span class="bold"><strong>the overloaded It is important to emphasize however that <span class="bold"><b>the overloaded
functions must have a common sequence of initial arguments</strong></span>. Otherwise, functions must have a common sequence of initial arguments</b></span>. Otherwise,
our scheme above will not work. If this is not the case, we have to wrap our scheme above will not work. If this is not the case, we have to wrap
our functions <a class="link" href="functions.html#python.overloading" title="Overloading">manually</a>. our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
</p> </p>
<p> <p>
Actually, we can mix and match manual wrapping of overloaded functions and Actually, we can mix and match manual wrapping of overloaded functions and
automatic wrapping through <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
and its sister, <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>. Following and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
up on our example presented in the section <a class="link" href="functions.html#python.overloading" title="Overloading">on up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
overloading</a>, since the first 4 overload functins have a common sequence overloading</a>, since the first 4 overload functins have a common sequence
of initial arguments, we can use <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
to automatically wrap the first three of the <code class="literal">def</code>s and to automatically wrap the first three of the <tt class="literal">def</tt>s and
manually wrap just the last. Here's how we'll do this: manually wrap just the last. Here's how we'll do this:
</p> </p>
<pre class="programlisting"><span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre> </pre>
<p> <p>
Create a member function pointers as above for both X::f overloads: Create a member function pointers as above for both X::f overloads:
</p> </p>
<pre class="programlisting"><span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <pre class="programlisting">
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span> <span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
</pre> </pre>
<p> <p>
Then... Then...
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">,</span> <span class="identifier">xf_overloads</span><span class="special">());</span> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">,</span> <span class="identifier">xf_overloads</span><span class="special">());</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
</pre> </pre>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -584,7 +615,7 @@ Namespaces are one honking great idea -- let's do more of those!
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,53 +1,53 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Building Hello World</title> <title> Building Hello World</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
<link rel="next" href="exposing.html" title="Exposing Classes"> <link rel="next" href="exposing.html" title=" Exposing Classes">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <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="python.hello"></a> Building Hello World</h2></div></div></div>
<a name="hello.from_start_to_finish"></a><h3> <a name="hello.from_start_to_finish"></a><h2>
<a name="id760024"></a> <a name="id387672"></a>
From Start To Finish From Start To Finish
</h3> </h2>
<p> <p>
Now the first thing you'd want to do is to build the Hello World module and Now the first thing you'd want to do is to build the Hello World module and
try it for yourself in Python. In this section, we will outline the steps necessary try it for yourself in Python. In this section, we will outline the steps necessary
to achieve that. We will use the build tool that comes bundled with every boost to achieve that. We will use the build tool that comes bundled with every boost
distribution: <span class="bold"><strong>bjam</strong></span>. distribution: <span class="bold"><b>bjam</b></span>.
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"> <tr><td colspan="2" align="left" valign="top">
<p> <p>
<span class="bold"><strong>Building without bjam</strong></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 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 written here should not be taken as "the one and only way". There
are of course other build tools apart from <code class="literal">bjam</code>. 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. Take note however that the preferred build tool for Boost.Python is bjam.
@@ -65,59 +65,65 @@
and run a python program using the extension. and run a python program using the extension.
</p> </p>
<p> <p>
The tutorial example can be found in the directory: <code class="literal">libs/python/example/tutorial</code>. The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
There, you can find: There, you can find:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
hello.cpp hello.cpp
</li> </li>
<li class="listitem"> <li>
hello.py hello.py
</li> </li>
<li class="listitem"> <li>
Jamroot Jamroot
</li> </li>
</ul></div> </ul></div>
<p> <p>
The <code class="literal">hello.cpp</code> file is our C++ hello world example. The The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
<code class="literal">Jamroot</code> is a minimalist <span class="emphasis"><em>bjam</em></span> script <tt class="literal">Jamroot</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
that builds the DLLs for us. Finally, <code class="literal">hello.py</code> is our Python that builds the DLLs for us. Finally, <tt class="literal">hello.py</tt> is our Python
program that uses the extension in <code class="literal">hello.cpp</code>. program that uses the extension in <tt class="literal">hello.cpp</tt>.
</p> </p>
<p> <p>
Before anything else, you should have the bjam executable in your boost directory Before anything else, you should have the bjam executable in your boost directory
or somewhere in your path such that <code class="literal">bjam</code> can be executed or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
in the command line. Pre-built Boost.Jam executables are available for most in 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>. 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> </p>
<a name="hello.let_s_jam_"></a><h3> <a name="hello.let_s_jam_"></a><h2>
<a name="id760177"></a> <a name="id386265"></a>
Let's Jam! Let's Jam!
</h3> </h2>
<p> <p>
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span> <span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
</p> </p>
<p> <p>
<a href="../../../../../example/tutorial/Jamroot" target="_top">Here</a> is our minimalist <a href="../../../../../example/tutorial/Jamroot" target="_top">Here</a> is our minimalist
Jamroot file. Simply copy the file and tweak <code class="literal">use-project boost</code> Jamroot file. Simply copy the file and tweak <tt class="literal">use-project boost</tt>
to where your boost root directory is and your OK. to where your boost root directory is and your OK.
</p> </p>
<p> <p>
The comments contained in the Jamrules file above should be sufficient to get The comments contained in the Jamrules file above should be sufficient to get
you going. you going.
</p> </p>
<a name="hello.running_bjam"></a><h3> <a name="hello.running_bjam"></a><h2>
<a name="id760225"></a> <a name="id386322"></a>
Running bjam Running bjam
</h3> </h2>
<p> <p>
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line <span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
interpreter. interpreter.
</p> </p>
<div class="blockquote"><blockquote class="blockquote"><p> <div class="blockquote"><blockquote class="blockquote">
Start it up. <p>
</p></blockquote></div> </p>
<p>
Start it up.
</p>
<p>
</p>
</blockquote></div>
<p> <p>
A file called user-config.jam in your home directory is used to configure your A file called user-config.jam in your home directory is used to configure your
tools. In Windows, your home directory can be found by typing: tools. In Windows, your home directory can be found by typing:
@@ -138,19 +144,20 @@ using python : 2.4 : C:/dev/tools<span class="emphasis"><em>Python</em></span> ;
<p> <p>
The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools. The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools.
The second rule provides information on Python, its version and where it is The second rule provides information on Python, its version and where it is
located. The above assumes that the Python installation is in <code class="literal">C:/dev/tools/Python/</code>. located. The above assumes that the Python installation is in <tt class="literal">C:/dev/tools/Python/</tt>.
If you have one fairly "standard" python installation for your platform, If you have one fairly "standard" python installation for your platform,
you might not need to do this. you might not need to do this.
</p> </p>
<p> <p>
Now we are ready... Be sure to <code class="literal">cd</code> to <code class="literal">libs/python/example/tutorial</code> Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
where the tutorial <code class="literal">"hello.cpp"</code> and the <code class="literal">"Jamroot"</code> where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamroot"</tt>
is situated. is situated.
</p> </p>
<p> <p>
Finally: Finally:
</p> </p>
<pre class="programlisting"><span class="identifier">bjam</span> <pre class="programlisting">
<span class="identifier">bjam</span>
</pre> </pre>
<p> <p>
It should be building now: It should be building now:
@@ -173,13 +180,19 @@ bjam
Or something similar. If all is well, you should now have built the DLLs and Or something similar. If all is well, you should now have built the DLLs and
run the Python program. run the Python program.
</p> </p>
<div class="blockquote"><blockquote class="blockquote"><p> <div class="blockquote"><blockquote class="blockquote">
<span class="bold"><strong>There you go... Have fun!</strong></span> <p>
</p></blockquote></div> </p>
<p>
<span class="bold"><b>There you go... Have fun!</b></span>
</p>
<p>
</p>
</blockquote></div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -189,7 +202,7 @@ bjam
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Iterators</title> <title>Iterators</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="embedding.html" title="Embedding"> <link rel="prev" href="embedding.html" title="Embedding">
<link rel="next" href="exception.html" title="Exception Translation"> <link rel="next" href="exception.html" title=" Exception Translation">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.iterators"></a>Iterators</h2></div></div></div> <a name="python.iterators"></a>Iterators</h2></div></div></div>
<p> <p>
@@ -30,41 +30,42 @@
iterators, but these are two very different beasts. iterators, but these are two very different beasts.
</p> </p>
<p> <p>
<span class="bold"><strong>C++ iterators:</strong></span> <span class="bold"><b>C++ iterators:</b></span>
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
C++ has 5 type categories (random-access, bidirectional, forward, input, C++ has 5 type categories (random-access, bidirectional, forward, input,
output) output)
</li> </li>
<li class="listitem"> <li>
There are 2 Operation categories: reposition, access There are 2 Operation categories: reposition, access
</li> </li>
<li class="listitem"> <li>
A pair of iterators is needed to represent a (first/last) range. A pair of iterators is needed to represent a (first/last) range.
</li> </li>
</ul></div> </ul></div>
<p> <p>
<span class="bold"><strong>Python Iterators:</strong></span> <span class="bold"><b>Python Iterators:</b></span>
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
1 category (forward) 1 category (forward)
</li> </li>
<li class="listitem"> <li>
1 operation category (next()) 1 operation category (next())
</li> </li>
<li class="listitem"> <li>
Raises StopIteration exception at end Raises StopIteration exception at end
</li> </li>
</ul></div> </ul></div>
<p> <p>
The typical Python iteration protocol: <code class="literal"><span class="bold"><strong>for y The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
in x...</strong></span></code> is as follows: in x...</b></span></tt> is as follows:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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 <pre class="programlisting">
<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><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="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 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
@@ -73,57 +74,59 @@
</span></pre> </span></pre>
<p> <p>
Boost.Python provides some mechanisms to make C++ iterators play along nicely Boost.Python provides some mechanisms to make C++ iterators play along nicely
as Python iterators. What we need to do is to produce appropriate <code class="computeroutput"><span class="identifier">__iter__</span></code> function from C++ iterators that 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 with the Python iteration protocol. For example: is compatible with the Python iteration protocol. For example:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">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> <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>
</pre> </pre>
<p> <p>
Or for use in class_&lt;&gt;: Or for use in class_&lt;&gt;:
</p> </p>
<pre class="programlisting"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</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> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</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>
</pre> </pre>
<p> <p>
<span class="bold"><strong>range</strong></span> <span class="bold"><b>range</b></span>
</p> </p>
<p> <p>
We can create a Python savvy iterator using the range function: We can create a Python savvy iterator using the range function:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
range(start, finish) range(start, finish)
</li> </li>
<li class="listitem"> <li>
range&lt;Policies,Target&gt;(start, finish) range&lt;Policies,Target&gt;(start, finish)
</li> </li>
</ul></div> </ul></div>
<p> <p>
Here, start/finish may be one of: Here, start/finish may be one of:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
member data pointers member data pointers
</li> </li>
<li class="listitem"> <li>
member function pointers member function pointers
</li> </li>
<li class="listitem"> <li>
adaptable function object (use Target parameter) adaptable function object (use Target parameter)
</li> </li>
</ul></div> </ul></div>
<p> <p>
<span class="bold"><strong>iterator</strong></span> <span class="bold"><b>iterator</b></span>
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> <div class="itemizedlist"><ul type="disc"><li>
iterator&lt;T, Policies&gt;() iterator&lt;T, Policies&gt;()
</li></ul></div> </li></ul></div>
<p> <p>
Given a container <code class="literal">T</code>, iterator is a shortcut that simply Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
calls <code class="literal">range</code> with &amp;T::begin, &amp;T::end. calls <tt class="literal">range</tt> with &amp;T::begin, &amp;T::end.
</p> </p>
<p> <p>
Let's put this into action... Here's an example from some hypothetical bogon Let's put this into action... Here's an example from some hypothetical bogon
@@ -131,7 +134,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="identifier">f</span> <span class="special">=</span> <span class="identifier">Field</span><span class="special">()</span> <pre class="programlisting">
<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="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">smash</span><span class="special">(</span><span class="identifier">x</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="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>
@@ -142,23 +146,25 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">"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> <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>
</pre> </pre>
<p> <p>
<span class="bold"><strong>stl_input_iterator</strong></span> <span class="bold"><b>stl_input_iterator</b></span>
</p> </p>
<p> <p>
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
we wish to go the other way, though: we'd like to pass a Python sequence to we wish to go the other way, though: we'd like to pass a Python sequence to
an STL algorithm or use it to initialize an STL container. We need to make an STL algorithm or use it to initialize an STL container. We need to make
a Python iterator look like an STL iterator. For that, we use <code class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special">&lt;&gt;</span></code>. a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special">&lt;&gt;</span></tt>.
Consider how we might implement a function that exposes <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></code> to Python: Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span> <pre class="programlisting">
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span>
<span class="comment">// Turn a Python sequence into an STL input range <span class="comment">// Turn a Python sequence into an STL input range
</span> <span class="identifier">stl_input_iterator</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span> </span> <span class="identifier">stl_input_iterator</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span>
@@ -172,18 +178,19 @@
</span> <span class="special">;</span> </span> <span class="special">;</span>
</pre> </pre>
<p> <p>
Now in Python, we can assign any integer sequence to <code class="computeroutput"><span class="identifier">list_int</span></code> Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
objects: objects:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span> <pre class="programlisting">
<span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</span><span class="special">([</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</span><span class="special">([</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span>
</pre> </pre>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -193,7 +200,7 @@
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,28 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Object Interface</title> <title> Object Interface</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="functions.html" title="Functions"> <link rel="prev" href="functions.html" title="Functions">
<link rel="next" href="embedding.html" title="Embedding"> <link rel="next" href="embedding.html" title="Embedding">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.object"></a> Object Interface</h2></div></div></div> <a name="python.object"></a> Object Interface</h2></div></div></div>
<div class="toc"><dl> <div class="toc"><dl>
@@ -35,26 +35,26 @@
Python is dynamically typed, unlike C++ which is statically typed. Python variables Python is dynamically typed, unlike C++ which is statically typed. Python variables
may hold an integer, a float, list, dict, tuple, str, long etc., among other may hold an integer, a float, list, dict, tuple, str, long etc., among other
things. In the viewpoint of Boost.Python and C++, these Pythonic variables things. In the viewpoint of Boost.Python and C++, these Pythonic variables
are just instances of class <code class="literal">object</code>. We will see in this are just instances of class <tt class="literal">object</tt>. We will see in this
chapter how to deal with Python objects. chapter how to deal with Python objects.
</p> </p>
<p> <p>
As mentioned, one of the goals of Boost.Python is to provide a bidirectional As mentioned, one of the goals of Boost.Python is to provide a bidirectional
mapping between C++ and Python while maintaining the Python feel. Boost.Python mapping between C++ and Python while maintaining the Python feel. Boost.Python
C++ <code class="literal">object</code>s are as close as possible to Python. This should C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
minimize the learning curve significantly. minimize the learning curve significantly.
</p> </p>
<p> <p>
<span class="inlinemediaobject"><img src="../images/python.png" alt="python"></span> <span class="inlinemediaobject"><img src="../images/python.png" alt="python"></span>
</p> </p>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div> <a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
<p> <p>
Class <code class="literal">object</code> wraps <code class="literal">PyObject*</code>. All the Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the
intricacies of dealing with <code class="literal">PyObject</code>s such as managing intricacies of dealing with <tt class="literal">PyObject</tt>s such as managing
reference counting are handled by the <code class="literal">object</code> class. C++ reference counting are handled by the <tt class="literal">object</tt> class. C++
object interoperability is seamless. Boost.Python C++ <code class="literal">object</code>s object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
can in fact be explicitly constructed from any C++ object. can in fact be explicitly constructed from any C++ object.
</p> </p>
<p> <p>
@@ -62,7 +62,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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="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">else</span><span class="special">:</span> <span class="keyword">else</span><span class="special">:</span>
@@ -77,7 +78,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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="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">else</span> <span class="keyword">else</span>
@@ -93,59 +95,63 @@
in C++, the look and feel should be immediately apparent to the Python coder. in C++, the look and feel should be immediately apparent to the Python coder.
</p> </p>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div> <a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
<p> <p>
Boost.Python comes with a set of derived <code class="literal">object</code> types Boost.Python comes with a set of derived <tt class="literal">object</tt> types
corresponding to that of Python's: corresponding to that of Python's:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
list list
</li> </li>
<li class="listitem"> <li>
dict dict
</li> </li>
<li class="listitem"> <li>
tuple tuple
</li> </li>
<li class="listitem"> <li>
str str
</li> </li>
<li class="listitem"> <li>
long_ long_
</li> </li>
<li class="listitem"> <li>
enum enum
</li> </li>
</ul></div> </ul></div>
<p> <p>
These derived <code class="literal">object</code> types act like real Python types. These derived <tt class="literal">object</tt> types act like real Python types.
For instance: For instance:
</p> </p>
<pre class="programlisting"><span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==&gt;</span> <span class="string">"1"</span> <pre class="programlisting">
<span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==&gt;</span> <span class="string">"1"</span>
</pre> </pre>
<p> <p>
Wherever appropriate, a particular derived <code class="literal">object</code> has Wherever appropriate, a particular derived <tt class="literal">object</tt> has
corresponding Python type's methods. For instance, <code class="literal">dict</code> corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
has a <code class="literal">keys()</code> method: has a <tt class="literal">keys()</tt> method:
</p> </p>
<pre class="programlisting"><span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span> <pre class="programlisting">
<span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
</pre> </pre>
<p> <p>
<code class="literal">make_tuple</code> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>. <tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
Example: Example:
</p> </p>
<pre class="programlisting"><span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
</pre> </pre>
<p> <p>
In C++, when Boost.Python <code class="literal">object</code>s are used as arguments In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
to functions, subtype matching is required. For example, when a function to functions, subtype matching is required. For example, when a function
<code class="literal">f</code>, as declared below, is wrapped, it will only accept <tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
instances of Python's <code class="literal">str</code> type and subtypes. instances of Python's <tt class="literal">str</tt> type and subtypes.
</p> </p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span> <pre class="programlisting">
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
<span class="special">{</span> <span class="special">{</span>
<span class="identifier">object</span> <span class="identifier">n2</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span> <span class="comment">// NAME = name.upper() <span class="identifier">object</span> <span class="identifier">n2</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span> <span class="comment">// NAME = name.upper()
</span> <span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <span class="comment">// better </span> <span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <span class="comment">// better
@@ -155,52 +161,54 @@
<p> <p>
In finer detail: In finer detail:
</p> </p>
<pre class="programlisting"><span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <pre class="programlisting">
<span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span>
</pre> </pre>
<p> <p>
Illustrates that we provide versions of the str type's methods as C++ member Illustrates that we provide versions of the str type's methods as C++ member
functions. functions.
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
</pre> </pre>
<p> <p>
Demonstrates that you can write the C++ equivalent of <code class="literal">"format" Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
% x,y,z</code> in Python, which is useful since there's no easy way to % x,y,z</tt> in Python, which is useful since there's no easy way to
do that in std C++. do that in std C++.
</p> </p>
<div class="sidebar"> <div class="sidebar"><p>
<p class="title"><b></b></p> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>Beware</b></span> the common pitfall
<p>
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>Beware</strong></span> the common pitfall
of forgetting that the constructors of most of Python's mutable types make of forgetting that the constructors of most of Python's mutable types make
copies, just as in Python. copies, just as in Python.
</p> </p></div>
</div>
<p> <p>
Python: Python:
</p> </p>
<pre class="programlisting"><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__ <pre class="programlisting">
<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="special">=</span> <span class="number">3</span> <span class="comment"># modifies the copy </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="special">=</span> <span class="number">3</span> <span class="comment"># modifies the copy
</span></pre> </span></pre>
<p> <p>
C++: C++:
</p> </p>
<pre class="programlisting"><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__ <pre class="programlisting">
<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><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></pre> </span></pre>
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h3> <a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
<a name="id771905"></a> <a name="id469586"></a>
class_&lt;T&gt; as objects class_&lt;T&gt; as objects
</h3> </h2>
<p> <p>
Due to the dynamic nature of Boost.Python objects, any <code class="literal">class_&lt;T&gt;</code> 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 may also be one of these types! The following code snippet wraps the class
(type) object. (type) object.
</p> </p>
<p> <p>
We can use this to create wrapped instances. Example: We can use this to create wrapped instances. Example:
</p> </p>
<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">vec345</span> <span class="special">=</span> <span class="special">(</span> <pre class="programlisting">
<span class="identifier">object</span> <span class="identifier">vec345</span> <span class="special">=</span> <span class="special">(</span>
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&gt;(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&gt;(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span> <span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span>
@@ -209,85 +217,91 @@
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span> <span class="special">==</span> <span class="number">5.0</span><span class="special">);</span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span> <span class="special">==</span> <span class="number">5.0</span><span class="special">);</span>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div> <a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
<p> <p>
At some point, we will need to get C++ values out of object instances. This At some point, we will need to get C++ values out of object instances. This
can be achieved with the <code class="literal">extract&lt;T&gt;</code> function. Consider can be achieved with the <tt class="literal">extract&lt;T&gt;</tt> function. Consider
the following: the following:
</p> </p>
<pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error <pre class="programlisting">
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
</span></pre> </span></pre>
<p> <p>
In the code above, we got a compiler error because Boost.Python <code class="literal">object</code> In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
can't be implicitly converted to <code class="literal">double</code>s. Instead, what can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
we wanted to do above can be achieved by writing: we wanted to do above can be achieved by writing:
</p> </p>
<pre class="programlisting"><span class="keyword">double</span> <span class="identifier">l</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span> <pre class="programlisting">
<span class="keyword">double</span> <span class="identifier">l</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span>
<span class="identifier">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">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> <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>
</pre> </pre>
<p> <p>
The first line attempts to extract the "length" attribute of the The first line attempts to extract the "length" attribute of the
Boost.Python <code class="literal">object</code>. The second line attempts to <span class="emphasis"><em>extract</em></span> Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
the <code class="literal">Vec2</code> object from held by the Boost.Python <code class="literal">object</code>. the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
</p> </p>
<p> <p>
Take note that we said "attempt to" above. What if the Boost.Python Take note that we said "attempt to" above. What if the Boost.Python
<code class="literal">object</code> does not really hold a <code class="literal">Vec2</code> <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 type? This is certainly a possibility considering the dynamic nature of Python
<code class="literal">object</code>s. To be on the safe side, if the C++ type can't <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, be extracted, an appropriate exception is thrown. To avoid an exception,
we need to test for extractibility: we need to test for extractibility:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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> <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>
</pre> </pre>
<p> <p>
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <code class="literal">extract&lt;T&gt;</code> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract&lt;T&gt;</tt>
facility in fact solves the mutable copying problem: facility in fact solves the mutable copying problem:
</p> </p>
<pre class="programlisting"><span class="identifier">dict</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">dict</span><span class="special">&gt;(</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> <pre class="programlisting">
<span class="identifier">dict</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">dict</span><span class="special">&gt;(</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">d</span><span class="special">[</span><span class="string">"whatever"</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies x.__dict__ ! <span class="identifier">d</span><span class="special">[</span><span class="string">"whatever"</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies x.__dict__ !
</span></pre> </span></pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.enums"></a>Enums</h3></div></div></div> <a name="python.enums"></a>Enums</h3></div></div></div>
<p> <p>
Boost.Python has a nifty facility to capture and wrap C++ enums. While Python Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
has no <code class="literal">enum</code> type, we'll often want to expose our C++ enums has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums
to Python as an <code class="literal">int</code>. Boost.Python's enum facility makes to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes
this easy while taking care of the proper conversions from Python's dynamic this easy while taking care of the proper conversions from Python's dynamic
typing to C++'s strong static typing (in C++, ints cannot be implicitly converted typing to C++'s strong static typing (in C++, ints cannot be implicitly converted
to enums). To illustrate, given a C++ enum: to enums). To illustrate, given a C++ enum:
</p> </p>
<pre class="programlisting"><span class="keyword">enum</span> <span class="identifier">choice</span> <span class="special">{</span> <span class="identifier">red</span><span class="special">,</span> <span class="identifier">blue</span> <span class="special">};</span> <pre class="programlisting">
<span class="keyword">enum</span> <span class="identifier">choice</span> <span class="special">{</span> <span class="identifier">red</span><span class="special">,</span> <span class="identifier">blue</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
the construct: the construct:
</p> </p>
<pre class="programlisting"><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">choice</span><span class="special">&gt;(</span><span class="string">"choice"</span><span class="special">)</span> <pre class="programlisting">
<span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">choice</span><span class="special">&gt;(</span><span class="string">"choice"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span> <span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span> <span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
<span class="special">;</span> <span class="special">;</span>
</pre> </pre>
<p> <p>
can be used to expose to Python. The new enum type is created in the current can be used to expose to Python. The new enum type is created in the current
<code class="literal">scope()</code>, which is usually the current module. The snippet <tt class="literal">scope()</tt>, which is usually the current module. The snippet
above creates a Python class derived from Python's <code class="literal">int</code> above creates a Python class derived from Python's <tt class="literal">int</tt>
type which is associated with the C++ type passed as its first parameter. type which is associated with the C++ type passed as its first parameter.
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"> <tr><td colspan="2" align="left" valign="top">
<p> <p>
<span class="bold"><strong>what is a scope?</strong></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 The scope is a class that has an associated global Python object which
@@ -301,7 +315,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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> <span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
</pre> </pre>
<p> <p>
@@ -310,7 +325,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">.</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">;</span> <span class="special">;</span>
@@ -325,7 +341,7 @@
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -335,7 +351,7 @@
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> <a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,27 +1,27 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>General Techniques</title> <title> General Techniques</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> <link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> <meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="start" href="../index.html" title="Chapter 1. python 1.0">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;python 2.0"> <link rel="up" href="../index.html" title="Chapter 1. python 1.0">
<link rel="prev" href="exception.html" title="Exception Translation"> <link rel="prev" href="exception.html" title=" Exception Translation">
</head> </head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr> <table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></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="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> <td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> <td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a> <a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.techniques"></a> General Techniques</h2></div></div></div> <a name="python.techniques"></a> General Techniques</h2></div></div></div>
<div class="toc"><dl> <div class="toc"><dl>
@@ -33,7 +33,7 @@
Here are presented some useful techniques that you can use while wrapping code Here are presented some useful techniques that you can use while wrapping code
with Boost.Python. with Boost.Python.
</p> </p>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div> <a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
<p> <p>
@@ -50,10 +50,11 @@
<p> <p>
We have a C++ library that works with sounds: reading and writing various We have a C++ library that works with sounds: reading and writing various
formats, applying filters to the sound data, etc. It is named (conveniently) formats, applying filters to the sound data, etc. It is named (conveniently)
<code class="literal">sounds</code>. Our library already has a neat C++ namespace hierarchy, <tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
like so: like so:
</p> </p>
<pre class="programlisting"><span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <pre class="programlisting">
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span>
</pre> </pre>
@@ -61,14 +62,16 @@
We would like to present this same hierarchy to the Python user, allowing We would like to present this same hierarchy to the Python user, allowing
him to write code like this: him to write code like this:
</p> </p>
<pre class="programlisting"><span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span> <pre class="programlisting">
<span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</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="comment"># echo is a C++ function <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="comment"># echo is a C++ function
</span></pre> </span></pre>
<p> <p>
The first step is to write the wrapping code. We have to export each module The first step is to write the wrapping code. We have to export each module
separately with Boost.Python, like this: separately with Boost.Python, like this:
</p> </p>
<pre class="programlisting"><span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">core</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span> <pre class="programlisting">
<span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">core</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">core</span><span class="special">)</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">{</span>
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <span class="identifier">namespace</span> <span class="special">*/</span> <span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <span class="identifier">namespace</span> <span class="special">*/</span>
@@ -90,18 +93,18 @@
<span class="special">}</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
Compiling these files will generate the following Python extensions: <code class="literal">core.pyd</code>, Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
<code class="literal">io.pyd</code> and <code class="literal">filters.pyd</code>. <tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"><p> <tr><td colspan="2" align="left" valign="top"><p>
The extension <code class="literal">.pyd</code> is used for python extension modules, 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 which are just shared libraries. Using the default for your system, like
<code class="literal">.so</code> for Unix and <code class="literal">.dll</code> for Windows, <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt> for Windows,
works just as well. works just as well.
</p></td></tr> </p></td></tr>
</table></div> </table></div>
@@ -115,18 +118,19 @@
io.pyd io.pyd
</pre> </pre>
<p> <p>
The file <code class="literal">__init__.py</code> is what tells Python that the directory The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
<code class="literal">sounds/</code> is actually a Python package. It can be a empty <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. file, but can also perform some magic, that will be shown later.
</p> </p>
<p> <p>
Now our package is ready. All the user has to do is put <code class="literal">sounds</code> 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> into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
and fire up the interpreter: and fire up the interpreter:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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">&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">&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> <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>
@@ -148,7 +152,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="comment">/* file core.cpp */</span> <pre class="programlisting">
<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="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">{</span>
<span class="special">...</span> <span class="special">...</span>
@@ -157,7 +162,7 @@
</pre> </pre>
<p> <p>
Note that we added an underscore to the module name. The filename will have Note that we added an underscore to the module name. The filename will have
to be changed to <code class="literal">_core.pyd</code> as well, and we do the same 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 to the other extension modules. Now, we change our package hierarchy like
so: so:
</p> </p>
@@ -180,62 +185,69 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">&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> <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>
</pre> </pre>
<p> <p>
which is not what we want. But here enters the <code class="literal">__init__.py</code> which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
magic: everything that is brought to the <code class="literal">__init__.py</code> namespace magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
can be accessed directly by the user. So, all we have to do is bring the can be accessed directly by the user. So, all we have to do is bring the
entire namespace from <code class="literal">_core.pyd</code> to <code class="literal">core/__init__.py</code>. entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
So add this line of code to <code class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</code>: So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
</p> </p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span> <pre class="programlisting">
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
</pre> </pre>
<p> <p>
We do the same for the other packages. Now the user accesses the functions We do the same for the other packages. Now the user accesses the functions
and classes in the extension modules like before: and classes in the extension modules like before:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">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="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>
</pre> </pre>
<p> <p>
with the additional benefit that we can easily add pure Python functions with the additional benefit that we can easily add pure Python functions
to any module, in a way that the user can't tell the difference between a to any module, in a way that the user can't tell the difference between a
C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span> C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span>
Python function, <code class="literal">echo_noise</code>, to the <code class="literal">filters</code> Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
package. This function applies both the <code class="literal">echo</code> and <code class="literal">noise</code> package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
filters in sequence in the given <code class="literal">sound</code> object. We create filters in sequence in the given <tt class="literal">sound</tt> object. We create
a file named <code class="literal">sounds/filters/echo_noise.py</code> and code our a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
function: function:
</p> </p>
<pre class="programlisting"><span class="keyword">import</span> <span class="identifier">_filters</span> <pre class="programlisting">
<span class="keyword">import</span> <span class="identifier">_filters</span>
<span class="keyword">def</span> <span class="identifier">echo_noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">):</span> <span class="keyword">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">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="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> <span class="keyword">return</span> <span class="identifier">s</span>
</pre> </pre>
<p> <p>
Next, we add this line to <code class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</code>: Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
</p> </p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span> <pre class="programlisting">
<span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
</pre> </pre>
<p> <p>
And that's it. The user now accesses this function like any other function And that's it. The user now accesses this function like any other function
from the <code class="literal">filters</code> package: from the <tt class="literal">filters</tt> package:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">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> <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>
</pre> </pre>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div> <a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
<p> <p>
Thanks to Python's flexibility, you can easily add new methods to a class, Thanks to Python's flexibility, you can easily add new methods to a class,
even after it was already created: even after it was already created:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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">&gt;&gt;&gt;</span> <span class="special">&gt;&gt;&gt;</span>
<span class="special">&gt;&gt;&gt;</span> <span class="comment"># a regular function <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><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>
@@ -254,11 +266,12 @@
</p> </p>
<p> <p>
We can do the same with classes that were wrapped with Boost.Python. Suppose We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <code class="literal">point</code> in C++: we have a class <tt class="literal">point</tt> in C++:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">point</span> <span class="special">{...};</span> <pre class="programlisting">
<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="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
<span class="special">{</span> <span class="special">{</span>
@@ -266,12 +279,13 @@
<span class="special">}</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
If we are using the technique from the previous session, <a class="link" href="techniques.html#python.creating_packages" title="Creating Packages">Creating 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 <code class="literal">geom/__init__.py</code>: Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="keyword">from</span> <span class="identifier">_geom</span> <span class="keyword">import</span> <span class="special">*</span> <pre class="programlisting">
<span class="keyword">from</span> <span class="identifier">_geom</span> <span class="keyword">import</span> <span class="special">*</span>
<span class="comment"># a regular function <span class="comment"># 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><span class="keyword">def</span> <span class="identifier">point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
@@ -281,29 +295,30 @@
</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> </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>
</pre> </pre>
<p> <p>
<span class="bold"><strong>All</strong></span> point instances created from C++ will <span class="bold"><b>All</b></span> point instances created from C++ will
also have this member function! This technique has several advantages: also have this member function! This technique has several advantages:
</p> </p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"> <div class="itemizedlist"><ul type="disc">
<li class="listitem"> <li>
Cut down compile times to zero for these additional functions Cut down compile times to zero for these additional functions
</li> </li>
<li class="listitem"> <li>
Reduce the memory footprint to virtually zero Reduce the memory footprint to virtually zero
</li> </li>
<li class="listitem"> <li>
Minimize the need to recompile Minimize the need to recompile
</li> </li>
<li class="listitem"> <li>
Rapid prototyping (you can move the code to C++ if required without changing Rapid prototyping (you can move the code to C++ if required without changing
the interface) the interface)
</li> </li>
</ul></div> </ul></div>
<p> <p>
You can even add a little syntactic sugar with the use of metaclasses. Let's 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. create a special metaclass that "injects" methods in other classes.
</p> </p>
<pre class="programlisting"><span class="comment"># The one Boost.Python uses for all wrapped classes. <pre class="programlisting">
<span class="comment"># The one Boost.Python uses for all wrapped classes.
</span><span class="comment"># You can use here any class exported by Boost instead of "point" </span><span class="comment"># 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><span class="identifier">BoostPythonMetaclass</span> <span class="special">=</span> <span class="identifier">point</span><span class="special">.</span><span class="identifier">__class__</span>
@@ -326,7 +341,8 @@
<p> <p>
Now let's see how it got: Now let's see how it got:
</p> </p>
<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">point</span><span class="special">()</span> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">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="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="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> <span class="identifier">foo</span><span class="special">!</span>
@@ -334,7 +350,8 @@
<p> <p>
Another useful idea is to replace constructors with factory functions: Another useful idea is to replace constructors with factory functions:
</p> </p>
<pre class="programlisting"><span class="identifier">_point</span> <span class="special">=</span> <span class="identifier">point</span> <pre class="programlisting">
<span class="identifier">_point</span> <span class="special">=</span> <span class="identifier">point</span>
<span class="keyword">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">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> <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>
@@ -346,7 +363,7 @@
support. support.
</p> </p>
</div> </div>
<div class="section"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div> <a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
<p> <p>
@@ -357,7 +374,8 @@
</p> </p>
<p> <p>
</p> </p>
<pre class="programlisting"><span class="comment">/* file point.cpp */</span> <pre class="programlisting">
<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">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="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>
@@ -376,10 +394,11 @@
<span class="special">}</span> <span class="special">}</span>
</pre> </pre>
<p> <p>
Now you create a file <code class="literal">main.cpp</code>, which contains the <code class="literal">BOOST_PYTHON_MODULE</code> Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
macro, and call the various export functions inside it. macro, and call the various export functions inside it.
</p> </p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">();</span> <pre class="programlisting">
<span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">();</span>
<span class="keyword">void</span> <span class="identifier">export_triangle</span><span class="special">();</span> <span class="keyword">void</span> <span class="identifier">export_triangle</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="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
@@ -392,7 +411,8 @@
Compiling and linking together all this files produces the same result as Compiling and linking together all this files produces the same result as
the usual approach: the usual approach:
</p> </p>
<pre class="programlisting"><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> <pre class="programlisting">
<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="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">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">triangle</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">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
@@ -412,21 +432,21 @@
</p> </p>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"><p> <tr><td colspan="2" align="left" valign="top"><p>
If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>, If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
take a look at the <code class="literal">--multiple</code> option, that generates take a look at the <tt class="literal">--multiple</tt> option, that generates
the wrappers in various files as demonstrated here. the wrappers in various files as demonstrated here.
</p></td></tr> </p></td></tr>
</table></div> </table></div>
<div class="note"><table border="0" summary="Note"> <div class="note"><table border="0" summary="Note">
<tr> <tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
<th align="left">Note</th> <th align="left">Note</th>
</tr> </tr>
<tr><td align="left" valign="top"><p> <tr><td colspan="2" align="left" valign="top"><p>
This method is useful too if you are getting the error message <span class="emphasis"><em>"fatal 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> 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>. when compiling a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.
@@ -436,7 +456,7 @@
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005 Joel <td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
de Guzman, David Abrahams<p> de Guzman, David Abrahams<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying 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"> file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
@@ -446,7 +466,7 @@
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a> <a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,5 +1,5 @@
[library python [library python
[version 2.0] [version 1.0]
[authors [de Guzman, Joel], [Abrahams, David]] [authors [de Guzman, Joel], [Abrahams, David]]
[copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams] [copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams]
[category inter-language support] [category inter-language support]
@@ -1381,10 +1381,10 @@ interpreter. This may be fixed in a future version of boost.python.]
[section Using the interpreter] [section Using the interpreter]
As you probably already know, objects in Python are reference-counted. As you probably already know, objects in Python are reference-counted.
Naturally, the [^PyObject]s of the Python C API are also reference-counted. Naturally, the [^PyObject]s of the Python\/C API are also reference-counted.
There is a difference however. While the reference-counting is fully There is a difference however. While the reference-counting is fully
automatic in Python, the Python C API requires you to do it automatic in Python, the Python\/C API requires you to do it
[@http://www.python.org/doc/current/c-api/refcounting.html by hand]. This is [@http://www.python.org/doc/current/api/refcounts.html by hand]. This is
messy and especially hard to get right in the presence of C++ exceptions. messy and especially hard to get right in the presence of C++ exceptions.
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
[@../../../v2/object.html object] class templates to automate the process. [@../../../v2/object.html object] class templates to automate the process.
@@ -1466,7 +1466,7 @@ If an exception occurs in the evaluation of the python expression,
The [^error_already_set] exception class doesn't carry any information in itself. The [^error_already_set] exception class doesn't carry any information in itself.
To find out more about the Python exception that occurred, you need to use the To find out more about the Python exception that occurred, you need to use the
[@http://www.python.org/doc/api/exceptionHandling.html exception handling functions] [@http://www.python.org/doc/api/exceptionHandling.html exception handling functions]
of the Python C API in your catch-statement. This can be as simple as calling of the Python/C API in your catch-statement. This can be as simple as calling
[@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to [@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to
print the exception's traceback to the console, or comparing the type of the print the exception's traceback to the console, or comparing the type of the
exception with those of the [@http://www.python.org/doc/api/standardExceptions.html exception with those of the [@http://www.python.org/doc/api/standardExceptions.html

View File

@@ -137,7 +137,7 @@
<td valign="top"><code>P::extract_return_type</code></td> <td valign="top"><code>P::extract_return_type</code></td>
<td>A model of <a href= <td>A model of <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a>.</td> "../../../doc/refmanual/metafunction.html">Metafunction</a>.</td>
<td>An MPL unary <a href= <td>An MPL unary <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td> "../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td>

View File

@@ -101,7 +101,7 @@ namespace boost { namespace python
struct arg struct arg
{ {
template &lt;class T&gt; template &lt;class T&gt;
arg &amp;operator = (T const &amp;value); arg &amp;perator = (T const &amp;value);
explicit arg (char const *name){elements[0].name = name;} explicit arg (char const *name){elements[0].name = name;}
}; };

View File

@@ -106,33 +106,6 @@
function from being treated as an exported symbol on platforms which function from being treated as an exported symbol on platforms which
support that distinction in-code</td> support that distinction in-code</td>
</tr> </tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_ENABLE_CDECL</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined, allows functions using the <code>__cdecl
</code> calling convention to be wrapped.</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_ENABLE_STDCALL</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined, allows functions using the <code>__stdcall
</code> calling convention to be wrapped.</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_ENABLE_FASTCALL</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined, allows functions using the <code>__fastcall
</code> calling convention to be wrapped.</td>
</tr>
</table> </table>
<h2><a name="lib-defined-impl"></a>Library Defined Implementation <h2><a name="lib-defined-impl"></a>Library Defined Implementation

View File

@@ -655,11 +655,6 @@ namespace boost { namespace python { namespace api
template &lt;class A0, class A1,...class An&gt; template &lt;class A0, class A1,...class An&gt;
object operator()(A0 const&amp;, A1 const&amp;,...An const&amp;) const; object operator()(A0 const&amp;, A1 const&amp;,...An const&amp;) const;
detail::args_proxy operator* () const;
object operator()(detail::args_proxy const &amp;args) const;
object operator()(detail::args_proxy const &amp;args,
detail::kwds_proxy const &amp;kwds) const;
// truth value testing // truth value testing
// //
typedef unspecified bool_type; typedef unspecified bool_type;
@@ -709,25 +704,6 @@ object operator()(A0 const&amp; a1, A1 const&amp; a2,...An const&amp; aN) const;
call&lt;object&gt;(object(*static_cast&lt;U*&gt;(this)).ptr(), a1, call&lt;object&gt;(object(*static_cast&lt;U*&gt;(this)).ptr(), a1,
a2,...aN)</dt> a2,...aN)</dt>
</dl> </dl>
<pre>
object operator()(detail::args_proxy const &amp;args) const;
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
call object with arguments given by the tuple <varname>args</varname></dt>
</dl>
<pre>
object operator()(detail::args_proxy const &amp;args,
detail::kwds_proxy const &amp;kwds) const;
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
call object with arguments given by the tuple <varname>args</varname>, and named
arguments given by the dictionary <varname>kwds</varname></dt>
</dl>
<pre> <pre>
operator bool_type() const; operator bool_type() const;
</pre> </pre>
@@ -835,8 +811,6 @@ namespace boost { namespace python { namespace api
object&amp; operator=(object const&amp;); object&amp; operator=(object const&amp;);
PyObject* ptr() const; PyObject* ptr() const;
bool is_none() const;
}; };
}}} }}}
</pre> </pre>
@@ -897,14 +871,6 @@ PyObject* ptr() const;
<dt><b>Returns:</b> a pointer to the internally-held Python <dt><b>Returns:</b> a pointer to the internally-held Python
object.</dt> object.</dt>
</dl> </dl>
<pre>
bool is_none() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> result of (ptr() == Py_None)</dt>
</dl>
<!-- --> <!-- -->
<h3><a name="proxy-spec"></a>Class template <code>proxy</code></h3> <h3><a name="proxy-spec"></a>Class template <code>proxy</code></h3>
@@ -1111,7 +1077,7 @@ object sum_items(object seq)
</pre> </pre>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan --> <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
15 March, 2010 27 May, 2008
<!--webbot bot="Timestamp" endspan i-checksum="39359" --> <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p> </p>

View File

@@ -1,93 +1,112 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/REC-html40/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"> <title>Boost.Python Pickle Support</title>
<head>
<title>Boost.Python Pickle Support</title>
</head>
<body> <div>
<div>
<img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"center" width="277" height="86" />
<hr />
<h1>Boost.Python Pickle Support</h1>Pickle is a Python module for object <img src="../../../../boost.png"
serialization, also known as persistence, marshalling, or flattening. alt="boost.png (6897 bytes)"
align="center"
width="277" height="86">
<p>It is often necessary to save and restore the contents of an object to <hr>
a file. One approach to this problem is to write a pair of functions that <h1>Boost.Python Pickle Support</h1>
read and write data from a file in a special format. A powerful
alternative approach is to use Python's pickle module. Exploiting
Python's ability for introspection, the pickle module recursively
converts nearly arbitrary Python objects into a stream of bytes that can
be written to a file.</p>
<p>The Boost Python Library supports the pickle module through the Pickle is a Python module for object serialization, also known
interface as described in detail in the <a href= as persistence, marshalling, or flattening.
"http://www.python.org/doc/current/lib/module-pickle.html">Python Library
Reference for pickle.</a> This interface involves the special methods
<tt>__getinitargs__</tt>, <tt>__getstate__</tt> and <tt>__setstate__</tt>
as described in the following. Note that Boost.Python is also fully
compatible with Python's cPickle module.</p>
<hr />
<h2>The Boost.Python Pickle Interface</h2>At the user level, the <p>
Boost.Python pickle interface involves three special methods: It is often necessary to save and restore the contents of an object to
a file. One approach to this problem is to write a pair of functions
that read and write data from a file in a special format. A powerful
alternative approach is to use Python's pickle module. Exploiting
Python's ability for introspection, the pickle module recursively
converts nearly arbitrary Python objects into a stream of bytes that
can be written to a file.
<dl> <p>
<dt><strong><tt>__getinitargs__</tt></strong></dt> The Boost Python Library supports the pickle module
through the interface as described in detail in the
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
>Python Library Reference for pickle.</a> This interface
involves the special methods <tt>__getinitargs__</tt>,
<tt>__getstate__</tt> and <tt>__setstate__</tt> as described
in the following. Note that Boost.Python is also fully compatible
with Python's cPickle module.
<dd> <hr>
When an instance of a Boost.Python extension class is pickled, the <h2>The Boost.Python Pickle Interface</h2>
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
This method must return a Python tuple (it is most convenient to use
a boost::python::tuple). When the instance is restored by the
unpickler, the contents of this tuple are used as the arguments for
the class constructor.
<p>If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt> At the user level, the Boost.Python pickle interface involves three special
will call the constructor (<tt>__init__</tt>) without arguments; methods:
i.e., the object must be default-constructible.</p>
</dd>
<dt><strong><tt>__getstate__</tt></strong></dt> <dl>
<dt>
<strong><tt>__getinitargs__</tt></strong>
<dd>
When an instance of a Boost.Python extension class is pickled, the
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
This method must return a Python tuple (it is most convenient to use
a boost::python::tuple). When the instance is restored by the
unpickler, the contents of this tuple are used as the arguments for
the class constructor.
<dd>When an instance of a Boost.Python extension class is pickled, the <p>
pickler tests if the instance has a <tt>__getstate__</tt> method. This If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt>
method should return a Python object representing the state of the will call the constructor (<tt>__init__</tt>) without arguments;
instance.</dd> i.e., the object must be default-constructible.
<dt><strong><tt>__setstate__</tt></strong></dt> <p>
<dt>
<strong><tt>__getstate__</tt></strong>
<dd>When an instance of a Boost.Python extension class is restored by <dd>
the unpickler (<tt>pickle.load</tt>), it is first constructed using the When an instance of a Boost.Python extension class is pickled, the
result of <tt>__getinitargs__</tt> as arguments (see above). pickler tests if the instance has a <tt>__getstate__</tt> method.
Subsequently the unpickler tests if the new instance has a This method should return a Python object representing the state of
<tt>__setstate__</tt> method. If so, this method is called with the the instance.
result of <tt>__getstate__</tt> (a Python object) as the argument.</dd>
</dl>The three special methods described above may be <tt>.def()</tt>'ed
individually by the user. However, Boost.Python provides an easy to use
high-level interface via the
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
must be defined as pairs. Use of this interface is demonstrated by the
following examples.
<hr />
<h2>Examples</h2>There are three files in <tt>boost/libs/python/test</tt> <p>
that show how to provide pickle support. <dt>
<hr /> <strong><tt>__setstate__</tt></strong>
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>The C++ <dd>
class in this example can be fully restored by passing the appropriate When an instance of a Boost.Python extension class is restored by the
argument to the constructor. Therefore it is sufficient to define the unpickler (<tt>pickle.load</tt>), it is first constructed using the
pickle interface method <tt>__getinitargs__</tt>. This is done in the result of <tt>__getinitargs__</tt> as arguments (see above). Subsequently
following way: the unpickler tests if the new instance has a <tt>__setstate__</tt>
method. If so, this method is called with the result of
<tt>__getstate__</tt> (a Python object) as the argument.
<ul> </dl>
<li>1. Definition of the C++ pickle function:
<pre> The three special methods described above may be <tt>.def()</tt>'ed
individually by the user. However, Boost.Python provides an easy to use
high-level interface via the
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
must be defined as pairs. Use of this interface is demonstrated by the
following examples.
<hr>
<h2>Examples</h2>
There are three files in
<tt>boost/libs/python/test</tt> that show how to
provide pickle support.
<hr>
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>
The C++ class in this example can be fully restored by passing the
appropriate argument to the constructor. Therefore it is sufficient
to define the pickle interface method <tt>__getinitargs__</tt>.
This is done in the following way:
<ul>
<li>1. Definition of the C++ pickle function:
<pre>
struct world_pickle_suite : boost::python::pickle_suite struct world_pickle_suite : boost::python::pickle_suite
{ {
static static
@@ -98,28 +117,26 @@
} }
}; };
</pre> </pre>
</li> <li>2. Establishing the Python binding:
<pre>
<li>2. Establishing the Python binding:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;()) class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ... // ...
.def_pickle(world_pickle_suite()) .def_pickle(world_pickle_suite())
// ... // ...
</pre> </pre>
</li> </ul>
</ul>
<hr />
<h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>The C++ <hr>
class in this example contains member data that cannot be restored by any <h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>
of the constructors. Therefore it is necessary to provide the
<tt>__getstate__</tt>/<tt>__setstate__</tt> pair of pickle interface
methods:
<ul> The C++ class in this example contains member data that cannot be
<li>1. Definition of the C++ pickle functions: restored by any of the constructors. Therefore it is necessary to
<pre> provide the <tt>__getstate__</tt>/<tt>__setstate__</tt> pair of
pickle interface methods:
<ul>
<li>1. Definition of the C++ pickle functions:
<pre>
struct world_pickle_suite : boost::python::pickle_suite struct world_pickle_suite : boost::python::pickle_suite
{ {
static static
@@ -144,76 +161,92 @@
} }
}; };
</pre> </pre>
</li> <li>2. Establishing the Python bindings for the entire suite:
<pre>
<li>2. Establishing the Python bindings for the entire suite:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;()) class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ... // ...
.def_pickle(world_pickle_suite()) .def_pickle(world_pickle_suite())
// ... // ...
</pre> </pre>
</li> </ul>
</ul>
<p>For simplicity, the <tt>__dict__</tt> is not included in the result of <p>
<tt>__getstate__</tt>. This is not generally recommended, but a valid For simplicity, the <tt>__dict__</tt> is not included in the result
approach if it is anticipated that the object's <tt>__dict__</tt> will of <tt>__getstate__</tt>. This is not generally recommended, but a
always be empty. Note that the safety guard described below will catch valid approach if it is anticipated that the object's
the cases where this assumption is violated.</p> <tt>__dict__</tt> will always be empty. Note that the safety guard
<hr /> described below will catch the cases where this assumption is violated.
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>This <hr>
example is similar to <a href= <h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
"../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the object's
<tt>__dict__</tt> is included in the result of <tt>__getstate__</tt>.
This requires a little more code but is unavoidable if the object's
<tt>__dict__</tt> is not always empty.
<hr />
<h2>Pitfall and Safety Guard</h2>The pickle protocol described above has This example is similar to <a
an important pitfall that the end user of a Boost.Python extension module href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the
might not be aware of: object's <tt>__dict__</tt> is included in the result of
<tt>__getstate__</tt>. This requires a little more code but is
unavoidable if the object's <tt>__dict__</tt> is not always empty.
<p><strong><tt>__getstate__</tt> is defined and the instance's <hr>
<tt>__dict__</tt> is not empty.</strong></p> <h2>Pitfall and Safety Guard</h2>
<p>The author of a Boost.Python extension class might provide a The pickle protocol described above has an important pitfall that the
<tt>__getstate__</tt> method without considering the possibilities end user of a Boost.Python extension module might not be aware of:
that:</p> <p>
<strong>
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt>
is not empty.
</strong>
<p>
<ul> The author of a Boost.Python extension class might provide a
<li>his class is used in Python as a base class. Most likely the <tt>__getstate__</tt> method without considering the possibilities
<tt>__dict__</tt> of instances of the derived class needs to be pickled that:
in order to restore the instances correctly.</li>
<li>the user adds items to the instance's <tt>__dict__</tt> directly. <p>
Again, the <tt>__dict__</tt> of the instance then needs to be <ul>
pickled.</li> <li>
</ul> his class is used in Python as a base class. Most likely the
<tt>__dict__</tt> of instances of the derived class needs to be
pickled in order to restore the instances correctly.
<p>To alert the user to this highly unobvious problem, a safety guard is <p>
provided. If <tt>__getstate__</tt> is defined and the instance's <li>
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has an the user adds items to the instance's <tt>__dict__</tt> directly.
attribute <tt>__getstate_manages_dict__</tt>. An exception is raised if Again, the <tt>__dict__</tt> of the instance then needs to be
this attribute is not defined:</p> pickled.
<pre>
</ul>
<p>
To alert the user to this highly unobvious problem, a safety guard is
provided. If <tt>__getstate__</tt> is defined and the instance's
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
raised if this attribute is not defined:
<pre>
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set) RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
</pre>To resolve this problem, it should first be established that the <tt> </pre>
__getstate__</tt> and <tt>__setstate__</tt> methods manage the
instances's <tt>__dict__</tt> correctly. Note that this can be done To resolve this problem, it should first be established that the
either at the C++ or the Python level. Finally, the safety guard should <tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
intentionally be overridden. E.g. in C++ (from <a href= instances's <tt>__dict__</tt> correctly. Note that this can be done
"../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>): either at the C++ or the Python level. Finally, the safety guard
<pre> should intentionally be overridden. E.g. in C++ (from
<a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
<pre>
struct world_pickle_suite : boost::python::pickle_suite struct world_pickle_suite : boost::python::pickle_suite
{ {
// ... // ...
static bool getstate_manages_dict() { return true; } static bool getstate_manages_dict() { return true; }
}; };
</pre>Alternatively in Python: </pre>
<pre>
Alternatively in Python:
<pre>
import your_bpl_module import your_bpl_module
class your_class(your_bpl_module.your_class): class your_class(your_bpl_module.your_class):
__getstate_manages_dict__ = 1 __getstate_manages_dict__ = 1
@@ -222,41 +255,54 @@
def __setstate__(self, state): def __setstate__(self, state):
# your code here # your code here
</pre> </pre>
<hr />
<h2>Practical Advice</h2> <hr>
<h2>Practical Advice</h2>
<ul> <ul>
<li>In Boost.Python extension modules with many extension classes, <li>
providing complete pickle support for all classes would be a In Boost.Python extension modules with many extension classes,
significant overhead. In general complete pickle support should only be providing complete pickle support for all classes would be a
implemented for extension classes that will eventually be pickled.</li> significant overhead. In general complete pickle support should
only be implemented for extension classes that will eventually
be pickled.
<li>Avoid using <tt>__getstate__</tt> if the instance can also be <p>
reconstructed by way of <tt>__getinitargs__</tt>. This automatically <li>
avoids the pitfall described above.</li> Avoid using <tt>__getstate__</tt> if the instance can also be
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
avoids the pitfall described above.
<li>If <tt>__getstate__</tt> is required, include the instance's <p>
<tt>__dict__</tt> in the Python object that is returned.</li> <li>
</ul> If <tt>__getstate__</tt> is required, include the instance's
<hr /> <tt>__dict__</tt> in the Python object that is returned.
<h2>Light-weight alternative: pickle support implemented in Python</h2> </ul>
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>The <hr>
<tt>pickle4.cpp</tt> example demonstrates an alternative technique for <h2>Light-weight alternative: pickle support implemented in Python</h2>
implementing pickle support. First we direct Boost.Python via the
<tt>class_::enable_pickling()</tt> member function to define only the <h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
basic attributes required for pickling:
<pre> The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
for implementing pickle support. First we direct Boost.Python via
the <tt>class_::enable_pickling()</tt> member function to define only
the basic attributes required for pickling:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;()) class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ... // ...
.enable_pickling() .enable_pickling()
// ... // ...
</pre>This enables the standard Python pickle interface as described in the </pre>
Python documentation. By "injecting" a <tt>__getinitargs__</tt> method into
the definition of the wrapped class we make all instances pickleable: This enables the standard Python pickle interface as described
<pre> in the Python documentation. By &quot;injecting&quot; a
<tt>__getinitargs__</tt> method into the definition of the wrapped
class we make all instances pickleable:
<pre>
# import the wrapped world class # import the wrapped world class
from pickle4_ext import world from pickle4_ext import world
@@ -266,15 +312,18 @@ the definition of the wrapped class we make all instances pickleable:
# now inject __getinitargs__ (Python is a dynamic language!) # now inject __getinitargs__ (Python is a dynamic language!)
world.__getinitargs__ = world_getinitargs world.__getinitargs__ = world_getinitargs
</pre>See also the <a href= </pre>
"../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python">
tutorial section</a> on injecting additional methods from Python.
<hr />
© Copyright Ralf W. Grosse-Kunstleve 2001-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)
<p>Updated: Feb 2004.</p> See also the
</div> <a href="../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python"
</body> >tutorial section</a> on injecting additional methods from Python.
</html>
<hr>
&copy; Copyright Ralf W. Grosse-Kunstleve 2001-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)
<p>
Updated: Feb 2004.
</div>

View File

@@ -167,13 +167,12 @@ PyObject* postcall(PyObject* args, PyObject* result);
class Bar class Bar
{ {
public:
Bar(int x) : x(x) {} Bar(int x) : x(x) {}
int get_x() const { return x; } int get_x() const { return x; }
void set_x(int x) { this-&gt;x = x; } void set_x(int x) { this-&gt;x = x; }
private: private:
int x; int x;
}; }
class Foo class Foo
{ {
@@ -190,7 +189,7 @@ class Foo
using namespace boost::python; using namespace boost::python;
BOOST_PYTHON_MODULE(internal_refs) BOOST_PYTHON_MODULE(internal_refs)
{ {
class_&lt;Bar&gt;("Bar", init&lt;int&gt;()) class_&lt;Bar&gt;("Bar")
.def("get_x", &amp;Bar::get_x) .def("get_x", &amp;Bar::get_x)
.def("set_x", &amp;Bar::set_x) .def("set_x", &amp;Bar::set_x)
; ;

View File

@@ -2,15 +2,6 @@
# Software License, Version 1.0. (See accompanying # Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
# Specify the path to the Boost project. If you move this project, # Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory. # adjust this path to refer to the Boost root directory.
use-project boost use-project boost
@@ -26,14 +17,6 @@ project
# source files after the colon separated by spaces. # source files after the colon separated by spaces.
python-extension hello_ext : hello.cpp ; python-extension hello_ext : hello.cpp ;
# Put the extension and Boost.Python DLL in the current directory, so
# that running script by hand works.
install convenient_copy
: hello_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
# A little "rule" (function) to clean up the syntax of declaring tests # A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules. # of these extension modules.
local rule run-test ( test-name : sources + ) local rule run-test ( test-name : sources + )

View File

@@ -38,10 +38,7 @@ namespace boost { namespace python {
# endif // CALL_DWA2002411_HPP # endif // CALL_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call.hpp) # line BOOST_PP_LINE(__LINE__, call.hpp)
@@ -79,5 +76,4 @@ call(PyObject* callable
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -37,10 +37,7 @@ namespace boost { namespace python {
# endif // CALL_METHOD_DWA2002411_HPP # endif // CALL_METHOD_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call_method.hpp) # line BOOST_PP_LINE(__LINE__, call_method.hpp)
@@ -79,5 +76,4 @@ call_method(PyObject* self, char const* name
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif // BOOST_PP_IS_ITERATING #endif // BOOST_PP_IS_ITERATING

View File

@@ -90,14 +90,6 @@ namespace detail
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr) BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
// Specialize converters for signed and unsigned T to Python Int // Specialize converters for signed and unsigned T to Python Int
#if PY_VERSION_HEX >= 0x03000000
# define BOOST_PYTHON_TO_INT(T) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyLong_FromLong(x), &PyLong_Type) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, ::PyLong_FromUnsignedLong(x), &PyLong_Type)
#else
# define BOOST_PYTHON_TO_INT(T) \ # define BOOST_PYTHON_TO_INT(T) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x), &PyInt_Type) \ BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x), &PyInt_Type) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE( \ BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
@@ -106,7 +98,6 @@ namespace detail
(std::numeric_limits<long>::max)()) \ (std::numeric_limits<long>::max)()) \
? ::PyLong_FromUnsignedLong(x) \ ? ::PyLong_FromUnsignedLong(x) \
: ::PyInt_FromLong(x), &PyInt_Type) : ::PyInt_FromLong(x), &PyInt_Type)
#endif
// Bool is not signed. // Bool is not signed.
#if PY_VERSION_HEX >= 0x02030000 #if PY_VERSION_HEX >= 0x02030000
@@ -122,48 +113,20 @@ BOOST_PYTHON_TO_INT(short)
BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(int)
BOOST_PYTHON_TO_INT(long) BOOST_PYTHON_TO_INT(long)
# if defined(_MSC_VER) && defined(_WIN64) && PY_VERSION_HEX < 0x03000000 // using Python's macro instead of Boost's - we don't seem to get the
/* Under 64-bit Windows std::size_t is "unsigned long long". To avoid // config right all the time.
getting a Python long for each std::size_t the value is checked before # ifdef HAVE_LONG_LONG
the conversion. A std::size_t is converted to a simple Python int BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyInt_Type)
if possible; a Python long appears only if the value is too small or BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyInt_Type)
too large to fit into a simple int. */
BOOST_PYTHON_TO_PYTHON_BY_VALUE(
signed BOOST_PYTHON_LONG_LONG,
( x < static_cast<signed BOOST_PYTHON_LONG_LONG>(
(std::numeric_limits<long>::min)())
|| x > static_cast<signed BOOST_PYTHON_LONG_LONG>(
(std::numeric_limits<long>::max)()))
? ::PyLong_FromLongLong(x)
: ::PyInt_FromLong(static_cast<long>(x)), &PyInt_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(
unsigned BOOST_PYTHON_LONG_LONG,
x > static_cast<unsigned BOOST_PYTHON_LONG_LONG>(
(std::numeric_limits<long>::max)())
? ::PyLong_FromUnsignedLongLong(x)
: ::PyInt_FromLong(static_cast<long>(x)), &PyInt_Type)
//
# elif defined(HAVE_LONG_LONG) // using Python's macro instead of Boost's
// - we don't seem to get the config right
// all the time.
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyLong_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyLong_Type)
# endif # endif
# undef BOOST_TO_PYTHON_INT # undef BOOST_TO_PYTHON_INT
#if PY_VERSION_HEX >= 0x03000000
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyUnicode_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyUnicode_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyUnicode_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type)
#else
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
#endif
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
# endif # endif
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x), &PyFloat_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x), &PyFloat_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type) BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type)

View File

@@ -34,9 +34,7 @@ struct pyobject_traits<PyObject>
// This is not an exhaustive list; should be expanded. // This is not an exhaustive list; should be expanded.
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type);
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List);
#if PY_VERSION_HEX < 0x03000000
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int);
#endif
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long);
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict);
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple); BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple);

View File

@@ -30,7 +30,7 @@ namespace registry
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info, PyTypeObject const* (*to_python_target_type)() = 0); BOOST_PYTHON_DECL void insert(to_python_function_t, type_info, PyTypeObject const* (*to_python_target_type)() = 0);
// Insert an lvalue from_python converter // Insert an lvalue from_python converter
BOOST_PYTHON_DECL void insert(convertible_function, type_info, PyTypeObject const* (*expected_pytype)() = 0); BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info, PyTypeObject const* (*expected_pytype)() = 0);
// Insert an rvalue from_python converter // Insert an rvalue from_python converter
BOOST_PYTHON_DECL void insert( BOOST_PYTHON_DECL void insert(

View File

@@ -45,14 +45,10 @@ struct shared_ptr_from_python
if (data->convertible == source) if (data->convertible == source)
new (storage) shared_ptr<T>(); new (storage) shared_ptr<T>();
else else
{
boost::shared_ptr<void> hold_convertible_ref_count(
(void*)0, shared_ptr_deleter(handle<>(borrowed(source))) );
// use aliasing constructor
new (storage) shared_ptr<T>( new (storage) shared_ptr<T>(
hold_convertible_ref_count, static_cast<T*>(data->convertible),
static_cast<T*>(data->convertible)); shared_ptr_deleter(handle<>(borrowed(source)))
} );
data->convertible = storage; data->convertible = storage;
} }

View File

@@ -55,8 +55,8 @@ inline decorated_type_info::decorated_type_info(type_info base_t, decoration dec
inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const
{ {
return m_decoration < rhs.m_decoration return m_decoration < rhs.m_decoration
|| (m_decoration == rhs.m_decoration || m_decoration == rhs.m_decoration
&& m_base_type < rhs.m_base_type); && m_base_type < rhs.m_base_type;
} }
inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const

View File

@@ -30,7 +30,7 @@ struct value_destroyer<
template <class T> template <class T>
static void execute(T const volatile* p) static void execute(T const volatile* p)
{ {
p->~T(); p->T::~T();
} }
}; };

View File

@@ -47,15 +47,8 @@ enum operator_id
op_ixor, op_ixor,
op_ior, op_ior,
op_complex, op_complex,
#if PY_VERSION_HEX >= 0x03000000
op_bool,
#else
op_nonzero, op_nonzero,
#endif
op_repr op_repr
#if PY_VERSION_HEX >= 0x03000000
,op_truediv
#endif
}; };
}}} // namespace boost::python::detail }}} // namespace boost::python::detail

View File

@@ -86,10 +86,7 @@ result(X const&, short = 0) { return 0; }
# endif // RESULT_DWA2002521_HPP # endif // RESULT_DWA2002521_HPP
/* --------------- function pointers --------------- */ /* --------------- function pointers --------------- */
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers)) # line BOOST_PP_LINE(__LINE__, result.hpp(function pointers))
@@ -131,5 +128,4 @@ boost::type<R>* result(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q, int = 0)
# undef N # undef N
# undef Q # undef Q
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -37,10 +37,7 @@ T& (* target(R (T::*)) )() { return 0; }
# endif // TARGET_DWA2002521_HPP # endif // TARGET_DWA2002521_HPP
/* --------------- function pointers --------------- */ /* --------------- function pointers --------------- */
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers)) # line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers))
@@ -82,5 +79,4 @@ T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
# undef N # undef N
# undef Q # undef Q
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -2,15 +2,13 @@
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#ifndef TRANSLATE_EXCEPTION_TDS20091020_HPP #ifndef TRANSLATE_EXCEPTION_DWA2002810_HPP
# define TRANSLATE_EXCEPTION_TDS20091020_HPP # define TRANSLATE_EXCEPTION_DWA2002810_HPP
# include <boost/python/detail/exception_handler.hpp> # include <boost/python/detail/exception_handler.hpp>
# include <boost/call_traits.hpp> # include <boost/call_traits.hpp>
# include <boost/type_traits/add_const.hpp> # include <boost/type_traits/add_const.hpp>
# include <boost/type_traits/add_reference.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/function/function0.hpp> # include <boost/function/function0.hpp>

View File

@@ -175,19 +175,6 @@ typedef int pid_t;
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
#endif #endif
// Define Python 3 macros for Python 2.x
#if PY_VERSION_HEX < 0x02060000
# define Py_TYPE(o) (((PyObject*)(o))->ob_type)
# define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt)
# define Py_SIZE(o) (((PyVarObject*)(o))->ob_size)
# define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#endif
#ifdef __MWERKS__ #ifdef __MWERKS__
# pragma warn_possunwant off # pragma warn_possunwant off
#elif _MSC_VER #elif _MSC_VER

View File

@@ -41,7 +41,7 @@ inline enum_<T>::enum_(char const* name, char const* doc )
, &enum_<T>::convertible_from_python , &enum_<T>::convertible_from_python
, &enum_<T>::construct , &enum_<T>::construct
, type_id<T>() , type_id<T>()
, doc , doc
) )
{ {
} }
@@ -79,11 +79,7 @@ void* enum_<T>::convertible_from_python(PyObject* obj)
template <class T> template <class T>
void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data) void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
{ {
#if PY_VERSION_HEX >= 0x03000000
T x = static_cast<T>(PyLong_AS_LONG(obj));
#else
T x = static_cast<T>(PyInt_AS_LONG(obj)); T x = static_cast<T>(PyInt_AS_LONG(obj));
#endif
void* const storage = ((converter::rvalue_from_python_storage<T>*)data)->storage.bytes; void* const storage = ((converter::rvalue_from_python_storage<T>*)data)->storage.bytes;
new (storage) T(x); new (storage) T(x);
data->convertible = storage; data->convertible = storage;

View File

@@ -18,7 +18,7 @@ template <class ExceptionType, class Translate>
void register_exception_translator(Translate translate, boost::type<ExceptionType>* = 0) void register_exception_translator(Translate translate, boost::type<ExceptionType>* = 0)
{ {
detail::register_exception_handler( detail::register_exception_handler(
boost::bind<bool>(detail::translate_exception<ExceptionType,Translate>(), _1, _2, translate) bind<bool>(detail::translate_exception<ExceptionType,Translate>(), _1, _2, translate)
); );
} }

View File

@@ -20,13 +20,6 @@ object
BOOST_PYTHON_DECL BOOST_PYTHON_DECL
eval(str string, object global = object(), object local = object()); eval(str string, object global = object(), object local = object());
// Execute an individual python statement from str.
// global and local are the global and local scopes respectively,
// used during execution.
object
BOOST_PYTHON_DECL
exec_statement(str string, object global = object(), object local = object());
// Execute python source code from str. // Execute python source code from str.
// global and local are the global and local scopes respectively, // global and local are the global and local scopes respectively,
// used during execution. // used during execution.

View File

@@ -19,7 +19,7 @@ namespace detail
{ {
void append(object_cref); // append object to end void append(object_cref); // append object to end
ssize_t count(object_cref value) const; // return number of occurrences of value long count(object_cref value) const; // return number of occurrences of value
void extend(object_cref sequence); // extend list by appending sequence elements void extend(object_cref sequence); // extend list by appending sequence elements
@@ -37,12 +37,8 @@ namespace detail
void reverse(); // reverse *IN PLACE* void reverse(); // reverse *IN PLACE*
void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1 void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
#if PY_VERSION_HEX >= 0x03000000
void sort(args_proxy const &args,
kwds_proxy const &kwds);
#else
void sort(object_cref cmpfunc); void sort(object_cref cmpfunc);
#endif
protected: protected:
list_base(); // new list list_base(); // new list
@@ -117,15 +113,13 @@ class list : public detail::list_base
base::remove(object(value)); base::remove(object(value));
} }
#if PY_VERSION_HEX <= 0x03000000
void sort() { base::sort(); } void sort() { base::sort(); }
template <class T> template <class T>
void sort(T const& value) void sort(T const& value)
{ {
base::sort(object(value)); base::sort(object(value));
} }
#endif
public: // implementation detail -- for internal use only public: // implementation detail -- for internal use only
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list, base) BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list, base)

View File

@@ -63,7 +63,7 @@ struct extract_member
{ {
static MemberType& execute(InstanceType& c) static MemberType& execute(InstanceType& c)
{ {
(void)Py_TYPE(&c); // static assertion (void)c.ob_type; // static assertion
return c.*member; return c.*member;
} }
}; };
@@ -75,7 +75,7 @@ struct extract_identity
{ {
static InstanceType& execute(InstanceType& c) static InstanceType& execute(InstanceType& c)
{ {
(void)Py_TYPE(&c); // static assertion (void)c.ob_type; // static assertion
return c; return c;
} }
}; };

View File

@@ -105,12 +105,12 @@ namespace detail
// If the BasePolicy_ supplied a result converter it would be // If the BasePolicy_ supplied a result converter it would be
// ignored; issue an error if it's not the default. // ignored; issue an error if it's not the default.
#if defined _MSC_VER && _MSC_VER < 1300 #if defined _MSC_VER && _MSC_VER < 1300
typedef is_same< typedef is_same<
typename BasePolicy_::result_converter typename BasePolicy_::result_converter
, default_result_converter , default_result_converter
> same_result_converter; > same_result_converter;
//see above for explanation //see above for explanation
BOOST_STATIC_ASSERT(same_result_converter::value) ; BOOST_STATIC_ASSERT(same_result_converter::value) ;
#else #else
BOOST_MPL_ASSERT_MSG( BOOST_MPL_ASSERT_MSG(
(is_same< (is_same<

View File

@@ -6,86 +6,48 @@
# define MODULE_INIT_DWA20020722_HPP # define MODULE_INIT_DWA20020722_HPP
# include <boost/python/detail/prefix.hpp> # include <boost/python/detail/prefix.hpp>
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/stringize.hpp>
# ifndef BOOST_PYTHON_MODULE_INIT # ifndef BOOST_PYTHON_MODULE_INIT
namespace boost { namespace python { namespace detail { namespace boost { namespace python { namespace detail {
# if PY_VERSION_HEX >= 0x03000000 BOOST_PYTHON_DECL void init_module(char const* name, void(*)());
BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)());
#else
BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)());
#endif
}}} }}}
# if PY_VERSION_HEX >= 0x03000000
# define _BOOST_PYTHON_MODULE_INIT(name) \
PyObject* BOOST_PP_CAT(PyInit_, name)() \
{ \
static PyModuleDef_Base initial_m_base = { \
PyObject_HEAD_INIT(NULL) \
0, /* m_init */ \
0, /* m_index */ \
0 /* m_copy */ }; \
static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; \
\
static struct PyModuleDef moduledef = { \
initial_m_base, \
BOOST_PP_STRINGIZE(name), \
0, /* m_doc */ \
-1, /* m_size */ \
initial_methods, \
0, /* m_reload */ \
0, /* m_traverse */ \
0, /* m_clear */ \
0, /* m_free */ \
}; \
\
return boost::python::detail::init_module( \
moduledef, BOOST_PP_CAT(init_module_, name) ); \
} \
void BOOST_PP_CAT(init_module_, name)()
# else
# define _BOOST_PYTHON_MODULE_INIT(name) \
void BOOST_PP_CAT(init,name)() \
{ \
boost::python::detail::init_module( \
BOOST_PP_STRINGIZE(name),&BOOST_PP_CAT(init_module_,name)); \
} \
void BOOST_PP_CAT(init_module_,name)()
# endif
# if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE) # if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE)
# define BOOST_PYTHON_MODULE_INIT(name) \ # define BOOST_PYTHON_MODULE_INIT(name) \
void BOOST_PP_CAT(init_module_,name)(); \ void init_module_##name(); \
extern "C" __declspec(dllexport) _BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name() \
{ \
boost::python::detail::init_module( \
#name,&init_module_##name); \
} \
void init_module_##name()
# elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY # elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# define BOOST_PYTHON_MODULE_INIT(name) \ # define BOOST_PYTHON_MODULE_INIT(name) \
void BOOST_PP_CAT(init_module_,name)(); \ void init_module_##name(); \
extern "C" __attribute__ ((visibility("default"))) _BOOST_PYTHON_MODULE_INIT(name) extern "C" __attribute__ ((visibility("default"))) void init##name() \
{ \
boost::python::detail::init_module(#name, &init_module_##name); \
} \
void init_module_##name()
# else # else
# define BOOST_PYTHON_MODULE_INIT(name) \ # define BOOST_PYTHON_MODULE_INIT(name) \
void BOOST_PP_CAT(init_module_,name)(); \ void init_module_##name(); \
extern "C" _BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name() \
{ \
boost::python::detail::init_module(#name, &init_module_##name); \
} \
void init_module_##name()
# endif # endif
# endif # endif
#endif // MODULE_INIT_DWA20020722_HPP #endif // MODULE_INIT_DWA20020722_HPP

View File

@@ -39,8 +39,6 @@ struct BOOST_PYTHON_DECL function : PyObject
void doc(object const& x); void doc(object const& x);
object const& name() const; object const& name() const;
object const& get_namespace() const { return m_namespace; }
private: // helper functions private: // helper functions
object signature(bool show_return_type=false) const; object signature(bool show_return_type=false) const;

View File

@@ -129,11 +129,7 @@ namespace detail
return class_<range_>(name, no_init) return class_<range_>(name, no_init)
.def("__iter__", identity_function()) .def("__iter__", identity_function())
.def( .def(
#if PY_VERSION_HEX >= 0x03000000
"__next__"
#else
"next" "next"
#endif
, make_function( , make_function(
next_fn() next_fn()
, policies , policies

View File

@@ -47,10 +47,7 @@ template <int nargs> struct make_holder;
# endif // MAKE_HOLDER_DWA20011215_HPP # endif // MAKE_HOLDER_DWA20011215_HPP
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, make_holder.hpp) # line BOOST_PP_LINE(__LINE__, make_holder.hpp)
@@ -105,5 +102,4 @@ struct make_holder<N>
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -10,9 +10,6 @@
# include <boost/python/converter/registered.hpp> # include <boost/python/converter/registered.hpp>
# include <boost/python/detail/decref_guard.hpp> # include <boost/python/detail/decref_guard.hpp>
# include <boost/python/detail/none.hpp> # include <boost/python/detail/none.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/mpl/or.hpp>
# include <boost/type_traits/is_union.hpp>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
@@ -24,7 +21,7 @@ struct make_instance_impl
template <class Arg> template <class Arg>
static inline PyObject* execute(Arg& x) static inline PyObject* execute(Arg& x)
{ {
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); BOOST_STATIC_ASSERT(is_class<T>::value);
PyTypeObject* type = Derived::get_class_object(x); PyTypeObject* type = Derived::get_class_object(x);
@@ -46,7 +43,7 @@ struct make_instance_impl
// Note the position of the internally-stored Holder, // Note the position of the internally-stored Holder,
// for the sake of destruction // for the sake of destruction
Py_SIZE(instance) = offsetof(instance_t, storage); instance->ob_size = offsetof(instance_t, storage);
// Release ownership of the python object // Release ownership of the python object
protect.cancel(); protect.cancel();

View File

@@ -35,8 +35,6 @@
# include <boost/detail/workaround.hpp> # include <boost/detail/workaround.hpp>
# include <boost/type_traits/remove_const.hpp>
namespace boost { namespace python { namespace boost { namespace python {
template <class T> class wrapper; template <class T> class wrapper;
@@ -124,29 +122,26 @@ inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_referen
template <class Pointer, class Value> 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, bool null_ptr_only)
{ {
typedef typename boost::remove_const< Value >::type non_const_value;
if (dst_t == python::type_id<Pointer>() if (dst_t == python::type_id<Pointer>()
&& !(null_ptr_only && get_pointer(this->m_p)) && !(null_ptr_only && get_pointer(this->m_p))
) )
return &this->m_p; return &this->m_p;
Value* p0 Value* p
# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) # if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
= static_cast<Value*>( get_pointer(this->m_p) ) = static_cast<Value*>( get_pointer(this->m_p) )
# else # else
= get_pointer(this->m_p) = get_pointer(this->m_p)
# endif # endif
; ;
non_const_value* p = const_cast<non_const_value*>( p0 );
if (p == 0) if (p == 0)
return 0; return 0;
if (void* wrapped = holds_wrapped(dst_t, p, p)) if (void* wrapped = holds_wrapped(dst_t, p, p))
return wrapped; return wrapped;
type_info src_t = python::type_id<non_const_value>(); type_info src_t = python::type_id<Value>();
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
} }
@@ -175,10 +170,7 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
# endif // POINTER_HOLDER_DWA20011215_HPP # endif // POINTER_HOLDER_DWA20011215_HPP
/* --------------- pointer_holder --------------- */ /* --------------- pointer_holder --------------- */
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp) # line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
@@ -220,5 +212,4 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -117,10 +117,7 @@ void* value_holder_back_reference<Value,Held>::holds(
// --------------- value_holder --------------- // --------------- value_holder ---------------
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder)) # line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder))
@@ -166,5 +163,4 @@ void* value_holder_back_reference<Value,Held>::holds(
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif #endif

View File

@@ -5,8 +5,6 @@
#ifndef OBJECT_CORE_DWA2002615_HPP #ifndef OBJECT_CORE_DWA2002615_HPP
# define OBJECT_CORE_DWA2002615_HPP # define OBJECT_CORE_DWA2002615_HPP
# define BOOST_PYTHON_OBJECT_HAS_IS_NONE // added 2010-03-15 by rwgk
# include <boost/python/detail/prefix.hpp> # include <boost/python/detail/prefix.hpp>
# include <boost/type.hpp> # include <boost/type.hpp>
@@ -44,12 +42,6 @@
namespace boost { namespace python { namespace boost { namespace python {
namespace detail
{
class kwds_proxy;
class args_proxy;
}
namespace converter namespace converter
{ {
template <class T> struct arg_to_python; template <class T> struct arg_to_python;
@@ -110,11 +102,6 @@ namespace api
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>)) # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
# include BOOST_PP_ITERATE() # include BOOST_PP_ITERATE()
detail::args_proxy operator* () const;
object operator()(detail::args_proxy const &args) const;
object operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const;
// truth value testing // truth value testing
// //
@@ -128,10 +115,6 @@ namespace api
const_object_objattribute attr(object const&) const; const_object_objattribute attr(object const&) const;
object_objattribute attr(object const&); object_objattribute attr(object const&);
// Wrap 'in' operator (aka. __contains__)
template <class T>
object contains(T const& key) const;
// item access // item access
// //
const_object_item operator[](object_cref) const; const_object_item operator[](object_cref) const;
@@ -236,14 +219,12 @@ namespace api
inline object_base(object_base const&); inline object_base(object_base const&);
inline object_base(PyObject* ptr); inline object_base(PyObject* ptr);
inline object_base& operator=(object_base const& rhs); object_base& operator=(object_base const& rhs);
inline ~object_base(); ~object_base();
// Underlying object access -- returns a borrowed reference // Underlying object access -- returns a borrowed reference
inline PyObject* ptr() const; PyObject* ptr() const;
inline bool is_none() const;
private: private:
PyObject* m_ptr; PyObject* m_ptr;
}; };
@@ -412,7 +393,7 @@ namespace api
static PyObject* static PyObject*
get(T const& x, U) get(T const& x, U)
{ {
return python::incref(get_managed_object(x, boost::python::tag)); return python::incref(get_managed_object(x, tag));
} }
}; };
@@ -435,71 +416,6 @@ template <class T> struct extract;
// implementation // implementation
// //
namespace detail
{
class call_proxy
{
public:
call_proxy(object target) : m_target(target) {}
operator object() const { return m_target;}
private:
object m_target;
};
class kwds_proxy : public call_proxy
{
public:
kwds_proxy(object o = object()) : call_proxy(o) {}
};
class args_proxy : public call_proxy
{
public:
args_proxy(object o) : call_proxy(o) {}
kwds_proxy operator* () const { return kwds_proxy(*this);}
};
}
template <typename U>
detail::args_proxy api::object_operators<U>::operator* () const
{
object_cref2 x = *static_cast<U const*>(this);
return boost::python::detail::args_proxy(x);
}
template <typename U>
object api::object_operators<U>::operator()(detail::args_proxy const &args) const
{
U const& self = *static_cast<U const*>(this);
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
args.operator object().ptr(),
0);
return object(boost::python::detail::new_reference(result));
}
template <typename U>
object api::object_operators<U>::operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const
{
U const& self = *static_cast<U const*>(this);
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
args.operator object().ptr(),
kwds.operator object().ptr());
return object(boost::python::detail::new_reference(result));
}
template <typename U>
template <class T>
object api::object_operators<U>::contains(T const& key) const
{
return this->attr("__contains__")(object(key));
}
inline object::object() inline object::object()
: object_base(python::incref(Py_None)) : object_base(python::incref(Py_None))
{} {}
@@ -543,11 +459,6 @@ inline PyObject* api::object_base::ptr() const
return m_ptr; return m_ptr;
} }
inline bool api::object_base::is_none() const
{
return (m_ptr == Py_None);
}
// //
// Converter specialization implementations // Converter specialization implementations
// //

View File

@@ -60,9 +60,7 @@ inline
object_operators<U>::operator bool_type() const object_operators<U>::operator bool_type() const
{ {
object_cref2 x = *static_cast<U const*>(this); object_cref2 x = *static_cast<U const*>(this);
int is_true = PyObject_IsTrue(x.ptr()); return PyObject_IsTrue(x.ptr()) ? &object::ptr : 0;
if (is_true < 0) throw_error_already_set();
return is_true ? &object::ptr : 0;
} }
template <class U> template <class U>
@@ -70,9 +68,7 @@ inline bool
object_operators<U>::operator!() const object_operators<U>::operator!() const
{ {
object_cref2 x = *static_cast<U const*>(this); object_cref2 x = *static_cast<U const*>(this);
int is_true = PyObject_IsTrue(x.ptr()); return !PyObject_IsTrue(x.ptr());
if (is_true < 0) throw_error_already_set();
return !is_true;
} }
# define BOOST_PYTHON_COMPARE_OP(op, opid) \ # define BOOST_PYTHON_COMPARE_OP(op, opid) \

View File

@@ -121,7 +121,8 @@ opaque<Pointee> opaque<Pointee>::instance;
template <class Pointee> template <class Pointee>
PyTypeObject opaque<Pointee>::type_object = PyTypeObject opaque<Pointee>::type_object =
{ {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(0)
0,
0, 0,
sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ), sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
0, 0,

View File

@@ -212,11 +212,7 @@ namespace self_ns \
BOOST_PYTHON_BINARY_OPERATOR(add, radd, +) BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -) BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *) BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
#if PY_VERSION_HEX >= 0x03000000 BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /)
#else
BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
#endif
BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %) BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<) BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>) BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
@@ -345,11 +341,7 @@ BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+) BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs) BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~) BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
#if PY_VERSION_HEX >= 0x03000000
BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
#else
BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!) BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
#endif
BOOST_PYTHON_UNARY_OPERATOR(int, long, int_) BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_) BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_) BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)

View File

@@ -8,7 +8,7 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
// Based on boost/ref.hpp, thus: // Based on boost/ref.hpp, thus:
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001 Peter Dimov // Copyright (C) 2001 Peter Dimov
# if _MSC_VER+0 >= 1020 # if _MSC_VER+0 >= 1020

View File

@@ -52,23 +52,16 @@ struct most_derived
// //
// template <class RT, class T0... class TN> // template <class RT, class T0... class TN>
// inline mpl::vector<RT, T0...TN> // inline mpl::vector<RT, T0...TN>
// get_signature(RT(BOOST_PYTHON_FN_CC *)(T0...TN), void* = 0) // get_signature(RT(*)(T0...TN), void* = 0)
// { // {
// return mpl::list<RT, T0...TN>(); // return mpl::list<RT, T0...TN>();
// } // }
// //
// where BOOST_PYTHON_FN_CC is a calling convention keyword, can be
//
// empty, for default calling convention
// __cdecl (if BOOST_PYTHON_ENABLE_CDECL is defined)
// __stdcall (if BOOST_PYTHON_ENABLE_STDCALL is defined)
// __fastcall (if BOOST_PYTHON_ENABLE_FASTCALL is defined)
//
// And, for an appropriate assortment of cv-qualifications:: // And, for an appropriate assortment of cv-qualifications::
// //
// template <class RT, class ClassT, class T0... class TN> // template <class RT, class ClassT, class T0... class TN>
// inline mpl::vector<RT, ClassT&, T0...TN> // inline mpl::vector<RT, ClassT&, T0...TN>
// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv)) // get_signature(RT(ClassT::*)(T0...TN) cv))
// { // {
// return mpl::list<RT, ClassT&, T0...TN>(); // return mpl::list<RT, ClassT&, T0...TN>();
// } // }
@@ -79,7 +72,7 @@ struct most_derived
// , typename most_derived<Target, ClassT>::type& // , typename most_derived<Target, ClassT>::type&
// , T0...TN // , T0...TN
// > // >
// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv), Target*) // get_signature(RT(ClassT::*)(T0...TN) cv), Target*)
// { // {
// return mpl::list<RT, ClassT&, T0...TN>(); // return mpl::list<RT, ClassT&, T0...TN>();
// } // }
@@ -94,8 +87,7 @@ struct most_derived
// //
// These functions extract the return type, class (for member // These functions extract the return type, class (for member
// functions) and arguments of the input signature and stuff them in // functions) and arguments of the input signature and stuff them in
// an mpl type sequence (the calling convention is dropped). // an mpl type sequence. Note that cv-qualification is dropped from
// Note that cv-qualification is dropped from
// the "hidden this" argument of member functions; that is a // the "hidden this" argument of member functions; that is a
// necessary sacrifice to ensure that an lvalue from_python converter // necessary sacrifice to ensure that an lvalue from_python converter
// is used. A pointer is not used so that None will be rejected for // is used. A pointer is not used so that None will be rejected for
@@ -108,64 +100,10 @@ struct most_derived
// //
// @group { // @group {
// 'default' calling convention
# define BOOST_PYTHON_FN_CC
# define BOOST_PP_ITERATION_PARAMS_1 \ # define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>)) (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
# include BOOST_PP_ITERATE() # include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FN_CC
// __cdecl calling convention
# if defined(BOOST_PYTHON_ENABLE_CDECL)
# define BOOST_PYTHON_FN_CC __cdecl
# define BOOST_PYTHON_FN_CC_IS_CDECL
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
# include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FN_CC
# undef BOOST_PYTHON_FN_CC_IS_CDECL
# endif // defined(BOOST_PYTHON_ENABLE_CDECL)
// __stdcall calling convention
# if defined(BOOST_PYTHON_ENABLE_STDCALL)
# define BOOST_PYTHON_FN_CC __stdcall
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
# include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FN_CC
# endif // defined(BOOST_PYTHON_ENABLE_STDCALL)
// __fastcall calling convention
# if defined(BOOST_PYTHON_ENABLE_FASTCALL)
# define BOOST_PYTHON_FN_CC __fastcall
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
# include BOOST_PP_ITERATE()
# undef BOOST_PYTHON_FN_CC
# endif // defined(BOOST_PYTHON_ENABLE_FASTCALL)
# undef BOOST_PYTHON_LIST_INC # undef BOOST_PYTHON_LIST_INC
// } // }
@@ -175,31 +113,21 @@ struct most_derived
# endif // SIGNATURE_JDG20020813_HPP # endif // SIGNATURE_JDG20020813_HPP
// For gcc 4.4 compatability, we must include the #elif BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
# define N BOOST_PP_ITERATION() # define N BOOST_PP_ITERATION()
// as 'get_signature(RT(*)(T0...TN), void* = 0)' is the same
// function as 'get_signature(RT(__cdecl *)(T0...TN), void* = 0)',
// we don't define it twice
# if !defined(BOOST_PYTHON_FN_CC_IS_CDECL)
template < template <
class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
inline BOOST_PYTHON_LIST_INC(N)< inline BOOST_PYTHON_LIST_INC(N)<
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)> RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0) get_signature(RT(*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0)
{ {
return BOOST_PYTHON_LIST_INC(N)< return BOOST_PYTHON_LIST_INC(N)<
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
>(); >();
} }
# endif // !defined(BOOST_PYTHON_FN_CC_IS_CDECL)
# undef N # undef N
# define BOOST_PP_ITERATION_PARAMS_2 \ # define BOOST_PP_ITERATION_PARAMS_2 \
@@ -215,7 +143,7 @@ template <
class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)> RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q) get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q)
{ {
return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
@@ -234,7 +162,7 @@ inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
> >
get_signature( get_signature(
RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q
, Target* , Target*
) )
{ {
@@ -248,5 +176,4 @@ get_signature(
# undef Q # undef Q
# undef N # undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif // !defined(BOOST_PP_IS_ITERATING) #endif // !defined(BOOST_PP_IS_ITERATING)

View File

@@ -37,12 +37,10 @@ namespace detail
long count(object_cref sub, object_cref start, object_cref end) const; long count(object_cref sub, object_cref start, object_cref end) const;
#if PY_VERSION_HEX < 0x03000000
object decode() const; object decode() const;
object decode(object_cref encoding) const; object decode(object_cref encoding) const;
object decode(object_cref encoding, object_cref errors) const; object decode(object_cref encoding, object_cref errors) const;
#endif
object encode() const; object encode() const;
object encode(object_cref encoding) const; object encode(object_cref encoding) const;
@@ -187,7 +185,6 @@ class str : public detail::str_base
return base::count(object(sub), object(start)); return base::count(object(sub), object(start));
} }
#if PY_VERSION_HEX < 0x03000000
object decode() const { return base::decode(); } object decode() const { return base::decode(); }
template<class T> template<class T>
@@ -201,7 +198,6 @@ class str : public detail::str_base
{ {
return base::decode(object(encoding),object(errors)); return base::decode(object(encoding),object(errors));
} }
#endif
object encode() const { return base::encode(); } object encode() const { return base::encode(); }
@@ -408,11 +404,7 @@ namespace converter
{ {
template <> template <>
struct object_manager_traits<str> struct object_manager_traits<str>
#if PY_VERSION_HEX >= 0x03000000
: pytype_object_manager_traits<&PyUnicode_Type,str>
#else
: pytype_object_manager_traits<&PyString_Type,str> : pytype_object_manager_traits<&PyString_Type,str>
#endif
{ {
}; };
} }

View File

@@ -37,20 +37,12 @@ void shared_ptr_deleter::operator()(void const*)
namespace namespace
{ {
// An lvalue conversion function which extracts a char const* from a // An lvalue conversion function which extracts a char const* from a
// Python String. // Python String.
#if PY_VERSION_HEX < 0x03000000
void* convert_to_cstring(PyObject* obj) void* convert_to_cstring(PyObject* obj)
{ {
return PyString_Check(obj) ? PyString_AsString(obj) : 0; return PyString_Check(obj) ? PyString_AsString(obj) : 0;
} }
#else
void* convert_to_cstring(PyObject* obj)
{
return PyUnicode_Check(obj) ? _PyUnicode_AsString(obj) : 0;
}
#endif
// Given a target type and a SlotPolicy describing how to perform a // Given a target type and a SlotPolicy describing how to perform a
// given conversion, registers from_python converters which use the // given conversion, registers from_python converters which use the
@@ -98,52 +90,6 @@ namespace
} }
}; };
// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
// "slot" which just returns its argument.
extern "C" PyObject* identity_unaryfunc(PyObject* x)
{
Py_INCREF(x);
return x;
}
unaryfunc py_object_identity = identity_unaryfunc;
#if PY_VERSION_HEX >= 0x03000000
// As in Python 3 there is only one integer type, we can have much
// simplified logic.
// XXX(bhy) maybe the code will work with 2.6 or even 2.5?
struct int_rvalue_from_python_base
{
static unaryfunc* get_slot(PyObject* obj)
{
return PyLong_Check(obj) ? &py_object_identity : 0;
}
static PyTypeObject const* get_pytype() {return &PyLong_Type;}
};
template <class T>
struct signed_int_rvalue_from_python : int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
long x = PyLong_AsLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(x);
}
};
template <class T>
struct unsigned_int_rvalue_from_python : int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
unsigned long x = PyLong_AsUnsignedLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(x);
}
};
#else // PY_VERSION_HEX >= 0x03000000
// A SlotPolicy for extracting signed integer types from Python objects // A SlotPolicy for extracting signed integer types from Python objects
struct signed_int_rvalue_from_python_base struct signed_int_rvalue_from_python_base
{ {
@@ -153,13 +99,8 @@ namespace
if (number_methods == 0) if (number_methods == 0)
return 0; return 0;
return ( return (PyInt_Check(obj) || PyLong_Check(obj))
#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT) ? &number_methods->nb_int : 0;
!PyBool_Check(obj) &&
#endif
(PyInt_Check(obj) || PyLong_Check(obj)))
? &number_methods->nb_int : 0;
} }
static PyTypeObject const* get_pytype() { return &PyInt_Type;} static PyTypeObject const* get_pytype() { return &PyInt_Type;}
}; };
@@ -175,7 +116,16 @@ namespace
return numeric_cast<T>(x); return numeric_cast<T>(x);
} }
}; };
// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
// "slot" which just returns its argument.
extern "C" PyObject* identity_unaryfunc(PyObject* x)
{
Py_INCREF(x);
return x;
}
unaryfunc py_object_identity = identity_unaryfunc;
// A SlotPolicy for extracting unsigned integer types from Python objects // A SlotPolicy for extracting unsigned integer types from Python objects
struct unsigned_int_rvalue_from_python_base struct unsigned_int_rvalue_from_python_base
{ {
@@ -185,11 +135,7 @@ namespace
if (number_methods == 0) if (number_methods == 0)
return 0; return 0;
return ( return (PyInt_Check(obj) || PyLong_Check(obj))
#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
!PyBool_Check(obj) &&
#endif
(PyInt_Check(obj) || PyLong_Check(obj)))
? &py_object_identity : 0; ? &py_object_identity : 0;
} }
static PyTypeObject const* get_pytype() { return &PyInt_Type;} static PyTypeObject const* get_pytype() { return &PyInt_Type;}
@@ -200,30 +146,12 @@ namespace
{ {
static T extract(PyObject* intermediate) static T extract(PyObject* intermediate)
{ {
if (PyLong_Check(intermediate)) { return numeric_cast<T>(
// PyLong_AsUnsignedLong() checks for negative overflow, so no PyLong_Check(intermediate)
// need to check it here. ? PyLong_AsUnsignedLong(intermediate)
unsigned long result = PyLong_AsUnsignedLong(intermediate); : PyInt_AS_LONG(intermediate));
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(result);
} else {
// None of PyInt_AsUnsigned*() functions check for negative
// overflow, so use PyInt_AS_LONG instead and check if number is
// negative, issuing the exception appropriately.
long result = PyInt_AS_LONG(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
if (result < 0) {
PyErr_SetString(PyExc_OverflowError, "can't convert negative"
" value to unsigned");
throw_error_already_set();
}
return numeric_cast<T>(result);
}
} }
}; };
#endif // PY_VERSION_HEX >= 0x03000000
// Checking Python's macro instead of Boost's - we don't seem to get // Checking Python's macro instead of Boost's - we don't seem to get
// the config right all the time. Furthermore, Python's is defined // the config right all the time. Furthermore, Python's is defined
@@ -236,9 +164,6 @@ namespace
{ {
static unaryfunc* get_slot(PyObject* obj) static unaryfunc* get_slot(PyObject* obj)
{ {
#if PY_VERSION_HEX >= 0x03000000
return PyLong_Check(obj) ? &py_object_identity : 0;
#else
PyNumberMethods* number_methods = obj->ob_type->tp_as_number; PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0) if (number_methods == 0)
return 0; return 0;
@@ -251,22 +176,19 @@ namespace
return &number_methods->nb_long; return &number_methods->nb_long;
else else
return 0; return 0;
#endif
} }
static PyTypeObject const* get_pytype() { return &PyLong_Type;} static PyTypeObject const* get_pytype() { return &PyInt_Type;}
}; };
struct long_long_rvalue_from_python : long_long_rvalue_from_python_base struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
{ {
static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate) static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
{ {
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate)) if (PyInt_Check(intermediate))
{ {
return PyInt_AS_LONG(intermediate); return PyInt_AS_LONG(intermediate);
} }
else else
#endif
{ {
BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate); BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate);
@@ -282,13 +204,11 @@ namespace
{ {
static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate) static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
{ {
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate)) if (PyInt_Check(intermediate))
{ {
return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate)); return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate));
} }
else else
#endif
{ {
unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate); unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate);
@@ -306,13 +226,7 @@ namespace
{ {
static unaryfunc* get_slot(PyObject* obj) static unaryfunc* get_slot(PyObject* obj)
{ {
#if PY_VERSION_HEX >= 0x03000000
return obj == Py_None || PyLong_Check(obj) ? &py_object_identity : 0;
#elif PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
return obj == Py_None || PyBool_Check(obj) ? &py_object_identity : 0;
#else
return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0; return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0;
#endif
} }
static bool extract(PyObject* intermediate) static bool extract(PyObject* intermediate)
@@ -341,10 +255,8 @@ namespace
// For integer types, return the tp_int conversion slot to avoid // For integer types, return the tp_int conversion slot to avoid
// creating a new object. We'll handle that below // creating a new object. We'll handle that below
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(obj)) if (PyInt_Check(obj))
return &number_methods->nb_int; return &number_methods->nb_int;
#endif
return (PyLong_Check(obj) || PyFloat_Check(obj)) return (PyLong_Check(obj) || PyFloat_Check(obj))
? &number_methods->nb_float : 0; ? &number_methods->nb_float : 0;
@@ -352,13 +264,11 @@ namespace
static double extract(PyObject* intermediate) static double extract(PyObject* intermediate)
{ {
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate)) if (PyInt_Check(intermediate))
{ {
return PyInt_AS_LONG(intermediate); return PyInt_AS_LONG(intermediate);
} }
else else
#endif
{ {
return PyFloat_AS_DOUBLE(intermediate); return PyFloat_AS_DOUBLE(intermediate);
} }
@@ -366,36 +276,22 @@ namespace
static PyTypeObject const* get_pytype() { return &PyFloat_Type;} static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
}; };
unaryfunc py_unicode_as_string_unaryfunc = PyUnicode_AsUTF8String;
// A SlotPolicy for extracting C++ strings from Python objects. // A SlotPolicy for extracting C++ strings from Python objects.
struct string_rvalue_from_python struct string_rvalue_from_python
{ {
// If the underlying object is "string-able" this will succeed // If the underlying object is "string-able" this will succeed
static unaryfunc* get_slot(PyObject* obj) static unaryfunc* get_slot(PyObject* obj)
{ {
#if PY_VERSION_HEX >= 0x03000000 return (PyString_Check(obj))
return (PyUnicode_Check(obj)) ? &py_unicode_as_string_unaryfunc : 0; ? &obj->ob_type->tp_str : 0;
#else
return (PyString_Check(obj)) ? &obj->ob_type->tp_str : 0;
#endif
}; };
// Remember that this will be used to construct the result object // Remember that this will be used to construct the result object
#if PY_VERSION_HEX >= 0x03000000
static std::string extract(PyObject* intermediate)
{
return std::string(PyBytes_AsString(intermediate),PyBytes_Size(intermediate));
}
static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
#else
static std::string extract(PyObject* intermediate) static std::string extract(PyObject* intermediate)
{ {
return std::string(PyString_AsString(intermediate),PyString_Size(intermediate)); return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
} }
static PyTypeObject const* get_pytype() { return &PyString_Type;} static PyTypeObject const* get_pytype() { return &PyString_Type;}
#endif
}; };
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
@@ -415,11 +311,7 @@ namespace
{ {
return PyUnicode_Check(obj) return PyUnicode_Check(obj)
? &py_object_identity ? &py_object_identity
#if PY_VERSION_HEX >= 0x03000000
: PyBytes_Check(obj)
#else
: PyString_Check(obj) : PyString_Check(obj)
#endif
? &py_encode_string ? &py_encode_string
: 0; : 0;
}; };
@@ -462,12 +354,10 @@ namespace
PyComplex_RealAsDouble(intermediate) PyComplex_RealAsDouble(intermediate)
, PyComplex_ImagAsDouble(intermediate)); , PyComplex_ImagAsDouble(intermediate));
} }
#if PY_VERSION_HEX < 0x03000000
else if (PyInt_Check(intermediate)) else if (PyInt_Check(intermediate))
{ {
return PyInt_AS_LONG(intermediate); return PyInt_AS_LONG(intermediate);
} }
#endif
else else
{ {
return PyFloat_AS_DOUBLE(intermediate); return PyFloat_AS_DOUBLE(intermediate);
@@ -479,20 +369,12 @@ namespace
BOOST_PYTHON_DECL PyObject* do_return_to_python(char x) BOOST_PYTHON_DECL PyObject* do_return_to_python(char x)
{ {
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_FromStringAndSize(&x, 1);
#else
return PyString_FromStringAndSize(&x, 1); return PyString_FromStringAndSize(&x, 1);
#endif
} }
BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x) BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x)
{ {
#if PY_VERSION_HEX >= 0x03000000
return x ? PyUnicode_FromString(x) : boost::python::detail::none();
#else
return x ? PyString_FromString(x) : boost::python::detail::none(); return x ? PyString_FromString(x) : boost::python::detail::none();
#endif
} }
BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x) BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x)
@@ -547,18 +429,13 @@ void initialize_builtin_converters()
slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>(); slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
// Add an lvalue converter for char which gets us char const* // Add an lvalue converter for char which gets us char const*
#if PY_VERSION_HEX < 0x03000000
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype); registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
#else
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyUnicode_Type>::get_pytype);
#endif
// Register by-value converters to std::string, std::wstring // Register by-value converters to std::string, std::wstring
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>(); slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
# endif # endif
slot_rvalue_from_python<std::string, string_rvalue_from_python>(); slot_rvalue_from_python<std::string, string_rvalue_from_python>();
} }
}}} // namespace boost::python::converter }}} // namespace boost::python::converter

View File

@@ -96,12 +96,7 @@ BOOST_PYTHON_DECL void* rvalue_from_python_stage2(
if (!data.convertible) if (!data.convertible)
{ {
handle<> msg( handle<> msg(
#if PY_VERSION_HEX >= 0x03000000 ::PyString_FromFormat(
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s" "No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s"
, converters.target_type.name() , converters.target_type.name()
, source->ob_type->tp_name , source->ob_type->tp_name
@@ -201,12 +196,7 @@ namespace
void throw_no_lvalue_from_python(PyObject* source, registration const& converters, char const* ref_type) void throw_no_lvalue_from_python(PyObject* source, registration const& converters, char const* ref_type)
{ {
handle<> msg( handle<> msg(
#if PY_VERSION_HEX >= 0x03000000 ::PyString_FromFormat(
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No registered converter was able to extract a C++ %s to type %s" "No registered converter was able to extract a C++ %s to type %s"
" from this Python object of type %s" " from this Python object of type %s"
, ref_type , ref_type
@@ -228,12 +218,7 @@ namespace
if (source->ob_refcnt <= 1) if (source->ob_refcnt <= 1)
{ {
handle<> msg( handle<> msg(
#if PY_VERSION_HEX >= 0x3000000 ::PyString_FromFormat(
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"Attempt to return dangling %s to object of type: %s" "Attempt to return dangling %s to object of type: %s"
, ref_type , ref_type
, converters.target_type.name())); , converters.target_type.name()));

View File

@@ -70,12 +70,7 @@ BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source)
if (this->m_to_python == 0) if (this->m_to_python == 0)
{ {
handle<> msg( handle<> msg(
#if PY_VERSION_HEX >= 0x3000000 ::PyString_FromFormat(
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No to_python (by-value) converter found for C++ type: %s" "No to_python (by-value) converter found for C++ type: %s"
, this->target_type.name() , this->target_type.name()
) )
@@ -243,7 +238,7 @@ namespace registry
} }
// Insert an rvalue from_python converter // Insert an rvalue from_python converter
void insert(convertible_function convertible void insert(void* (*convertible)(PyObject*)
, constructor_function construct , constructor_function construct
, type_info key , type_info key
, PyTypeObject const* (*exp_pytype)()) , PyTypeObject const* (*exp_pytype)())
@@ -261,7 +256,7 @@ namespace registry
} }
// Insert an rvalue from_python converter // Insert an rvalue from_python converter
void push_back(convertible_function convertible void push_back(void* (*convertible)(PyObject*)
, constructor_function construct , constructor_function construct
, type_info key , type_info key
, PyTypeObject const* (*exp_pytype)()) , PyTypeObject const* (*exp_pytype)())

View File

@@ -84,7 +84,7 @@ object dict_base::get(object_cref k, object_cref d) const
bool dict_base::has_key(object_cref k) const bool dict_base::has_key(object_cref k) const
{ {
return extract<bool>(this->contains(k)); return extract<bool>(this->attr("has_key")(k));
} }
list dict_base::items() const list dict_base::items() const

View File

@@ -5,7 +5,6 @@
#include <boost/python/exec.hpp> #include <boost/python/exec.hpp>
#include <boost/python/borrowed.hpp> #include <boost/python/borrowed.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp> #include <boost/python/extract.hpp>
#include <boost/python/handle.hpp> #include <boost/python/handle.hpp>
@@ -16,15 +15,6 @@ namespace python
object BOOST_PYTHON_DECL eval(str string, object global, object local) object BOOST_PYTHON_DECL eval(str string, object global, object local)
{ {
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet. // should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string); char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr()); PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr());
@@ -34,15 +24,6 @@ object BOOST_PYTHON_DECL eval(str string, object global, object local)
object BOOST_PYTHON_DECL exec(str string, object global, object local) object BOOST_PYTHON_DECL exec(str string, object global, object local)
{ {
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet. // should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string); char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr());
@@ -50,53 +31,18 @@ object BOOST_PYTHON_DECL exec(str string, object global, object local)
return object(detail::new_reference(result)); return object(detail::new_reference(result));
} }
object BOOST_PYTHON_DECL exec_statement(str string, object global, object local)
{
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_single_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
// Execute python source code from file filename. // Execute python source code from file filename.
// global and local are the global and local scopes respectively, // global and local are the global and local scopes respectively,
// used during execution. // used during execution.
object BOOST_PYTHON_DECL exec_file(str filename, object global, object local) object BOOST_PYTHON_DECL exec_file(str filename, object global, object local)
{ {
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet. // should be 'char const *' but older python versions don't use 'const' yet.
char *f = python::extract<char *>(filename); char *f = python::extract<char *>(filename);
#if PY_VERSION_HEX >= 0x03000000
// TODO(bhy) temporary workaround for Python 3.
// should figure out a way to avoid binary incompatibilities as the Python 2
// version did.
FILE *fs = fopen(f, "r");
#else
// Let python open the file to avoid potential binary incompatibilities. // Let python open the file to avoid potential binary incompatibilities.
PyObject *pyfile = PyFile_FromString(f, const_cast<char*>("r")); PyObject *pyfile = PyFile_FromString(f, const_cast<char*>("r"));
if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file"); if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file");
python::handle<> file(pyfile); python::handle<> file(pyfile);
FILE *fs = PyFile_AsFile(file.get()); PyObject* result = PyRun_File(PyFile_AsFile(file.get()),
#endif
PyObject* result = PyRun_File(fs,
f, f,
Py_file_input, Py_file_input,
global.ptr(), local.ptr()); global.ptr(), local.ptr());

View File

@@ -48,11 +48,7 @@ void list_base::extend(object_cref sequence)
long list_base::index(object_cref value) const long list_base::index(object_cref value) const
{ {
object result_obj(this->attr("index")(value)); object result_obj(this->attr("index")(value));
#if PY_VERSION_HEX >= 0x03000000
ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
#else
long result = PyInt_AsLong(result_obj.ptr()); long result = PyInt_AsLong(result_obj.ptr());
#endif
if (result == -1) if (result == -1)
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -73,11 +69,7 @@ void list_base::insert(ssize_t index, object_cref item)
void list_base::insert(object const& index, object_cref x) void list_base::insert(object const& index, object_cref x)
{ {
#if PY_VERSION_HEX >= 0x03000000
ssize_t index_ = PyLong_AsSsize_t(index.ptr());
#else
long index_ = PyInt_AsLong(index.ptr()); long index_ = PyInt_AsLong(index.ptr());
#endif
if (index_ == -1 && PyErr_Occurred()) if (index_ == -1 && PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
this->insert(index_, x); this->insert(index_, x);
@@ -129,29 +121,17 @@ void list_base::sort()
} }
} }
#if PY_VERSION_HEX >= 0x03000000
void list_base::sort(args_proxy const &args,
kwds_proxy const &kwds)
{
this->attr("sort")(args, kwds);
}
#else
void list_base::sort(object_cref cmpfunc) void list_base::sort(object_cref cmpfunc)
{ {
this->attr("sort")(cmpfunc); this->attr("sort")(cmpfunc);
} }
#endif
// For some reason, moving this to the end of the TU suppresses an ICE // For some reason, moving this to the end of the TU suppresses an ICE
// with vc6. // with vc6.
ssize_t list_base::count(object_cref value) const long list_base::count(object_cref value) const
{ {
object result_obj(this->attr("count")(value)); object result_obj(this->attr("count")(value));
#if PY_VERSION_HEX >= 0x03000000
ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
#else
long result = PyInt_AsLong(result_obj.ptr()); long result = PyInt_AsLong(result_obj.ptr());
#endif
if (result == -1) if (result == -1)
throw_error_already_set(); throw_error_already_set();
return result; return result;

View File

@@ -11,23 +11,6 @@
namespace boost { namespace python { namespace detail { namespace boost { namespace python { namespace detail {
namespace
{
PyObject* init_module_in_scope(PyObject* m, void(*init_function)())
{
if (m != 0)
{
// Create the current module scope
object m_obj(((borrowed_reference_t*)m));
scope current_module(m_obj);
handle_exception(init_function);
}
return m;
}
}
BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char const* doc) BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char const* doc)
{ {
// Use function::add_to_namespace to achieve overloading if // Use function::add_to_namespace to achieve overloading if
@@ -36,30 +19,26 @@ BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char
objects::add_to_namespace(current, name, x, doc); objects::add_to_namespace(current, name, x, doc);
} }
#if PY_VERSION_HEX >= 0x03000000
PyObject* init_module(PyModuleDef& moduledef, void(*init_function)())
{
return init_module_in_scope(
PyModule_Create(&moduledef),
init_function);
}
#else
namespace namespace
{ {
PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } };
} }
BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*init_function)()) BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)())
{ {
return init_module_in_scope(
Py_InitModule(const_cast<char*>(name), initial_methods), PyObject* m
init_function); = Py_InitModule(const_cast<char*>(name), initial_methods);
}
#endif if (m != 0)
{
// Create the current module scope
object m_obj(((borrowed_reference_t*)m));
scope current_module(m_obj);
handle_exception(init_function);
}
}
}}} // namespace boost::python::detail }}} // namespace boost::python::detail

View File

@@ -67,44 +67,8 @@ extern "C"
PyObject *prop_set; PyObject *prop_set;
PyObject *prop_del; PyObject *prop_del;
PyObject *prop_doc; PyObject *prop_doc;
int getter_doc;
} propertyobject; } propertyobject;
// Copied from Python source and removed the part for setting docstring,
// since we don't have a setter for __doc__ and trying to set it will
// cause the init fail.
static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
propertyobject *prop = (propertyobject *)self;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
kwlist, &get, &set, &del, &doc))
return -1;
if (get == Py_None)
get = NULL;
if (set == Py_None)
set = NULL;
if (del == Py_None)
del = NULL;
Py_XINCREF(get);
Py_XINCREF(set);
Py_XINCREF(del);
Py_XINCREF(doc);
prop->prop_get = get;
prop->prop_set = set;
prop->prop_del = del;
prop->prop_doc = doc;
prop->getter_doc = 0;
return 0;
}
static PyObject * static PyObject *
static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/) static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
{ {
@@ -142,9 +106,10 @@ extern "C"
} }
static PyTypeObject static_data_object = { static PyTypeObject static_data_object = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(0)//&PyType_Type)
0,
const_cast<char*>("Boost.Python.StaticProperty"), const_cast<char*>("Boost.Python.StaticProperty"),
sizeof(propertyobject), PyType_Type.tp_basicsize,
0, 0,
0, /* tp_dealloc */ 0, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
@@ -178,11 +143,11 @@ static PyTypeObject static_data_object = {
static_data_descr_get, /* tp_descr_get */ static_data_descr_get, /* tp_descr_get */
static_data_descr_set, /* tp_descr_set */ static_data_descr_set, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
property_init, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
0, // filled in with type_new /* tp_new */ 0, // filled in with type_new /* tp_new */
0, // filled in with __PyObject_GC_Del /* tp_free */ 0, // filled in with __PyObject_GC_Del /* tp_free */
0, /* tp_is_gc */ (inquiry)type_is_gc, /* tp_is_gc */
0, /* tp_bases */ 0, /* tp_bases */
0, /* tp_mro */ 0, /* tp_mro */
0, /* tp_cache */ 0, /* tp_cache */
@@ -195,20 +160,17 @@ static PyTypeObject static_data_object = {
namespace objects namespace objects
{ {
#if PY_VERSION_HEX < 0x03000000
// XXX Not sure why this run into compiling error in Python 3
extern "C" extern "C"
{ {
// This declaration needed due to broken Python 2.2 headers // This declaration needed due to broken Python 2.2 headers
extern DL_IMPORT(PyTypeObject) PyProperty_Type; extern DL_IMPORT(PyTypeObject) PyProperty_Type;
} }
#endif
BOOST_PYTHON_DECL PyObject* static_data() BOOST_PYTHON_DECL PyObject* static_data()
{ {
if (static_data_object.tp_dict == 0) if (static_data_object.tp_dict == 0)
{ {
Py_TYPE(&static_data_object) = &PyType_Type; static_data_object.ob_type = &PyType_Type;
static_data_object.tp_base = &PyProperty_Type; static_data_object.tp_base = &PyProperty_Type;
if (PyType_Ready(&static_data_object)) if (PyType_Ready(&static_data_object))
return 0; return 0;
@@ -241,14 +203,15 @@ extern "C"
// If we found a static data descriptor, call it directly to // If we found a static data descriptor, call it directly to
// force it to set the static data member // force it to set the static data member
if (a != 0 && PyObject_IsInstance(a, objects::static_data())) if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
return Py_TYPE(a)->tp_descr_set(a, obj, value); return a->ob_type->tp_descr_set(a, obj, value);
else else
return PyType_Type.tp_setattro(obj, name, value); return PyType_Type.tp_setattro(obj, name, value);
} }
} }
static PyTypeObject class_metatype_object = { static PyTypeObject class_metatype_object = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(0)//&PyType_Type)
0,
const_cast<char*>("Boost.Python.class"), const_cast<char*>("Boost.Python.class"),
PyType_Type.tp_basicsize, PyType_Type.tp_basicsize,
0, 0,
@@ -303,7 +266,7 @@ static PyTypeObject class_metatype_object = {
// object. // object.
void instance_holder::install(PyObject* self) throw() void instance_holder::install(PyObject* self) throw()
{ {
assert(Py_TYPE(Py_TYPE(self)) == &class_metatype_object); assert(self->ob_type->ob_type == &class_metatype_object);
m_next = ((objects::instance<>*)self)->objects; m_next = ((objects::instance<>*)self)->objects;
((objects::instance<>*)self)->objects = this; ((objects::instance<>*)self)->objects = this;
} }
@@ -316,7 +279,7 @@ namespace objects
{ {
if (class_metatype_object.tp_dict == 0) if (class_metatype_object.tp_dict == 0)
{ {
Py_TYPE(&class_metatype_object) = &PyType_Type; class_metatype_object.ob_type = &PyType_Type;
class_metatype_object.tp_base = &PyType_Type; class_metatype_object.tp_base = &PyType_Type;
if (PyType_Ready(&class_metatype_object)) if (PyType_Ready(&class_metatype_object))
return type_handle(); return type_handle();
@@ -345,7 +308,7 @@ namespace objects
Py_XDECREF(kill_me->dict); Py_XDECREF(kill_me->dict);
Py_TYPE(inst)->tp_free(inst); inst->ob_type->tp_free(inst);
} }
static PyObject * static PyObject *
@@ -355,12 +318,7 @@ namespace objects
PyObject* d = type_->tp_dict; PyObject* d = type_->tp_dict;
PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__")); PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
ssize_t instance_size = instance_size_obj ? long instance_size = instance_size_obj ? PyInt_AsLong(instance_size_obj) : 0;
#if PY_VERSION_HEX >= 0x03000000
PyLong_AsSsize_t(instance_size_obj) : 0;
#else
PyInt_AsLong(instance_size_obj) : 0;
#endif
if (instance_size < 0) if (instance_size < 0)
instance_size = 0; instance_size = 0;
@@ -374,12 +332,7 @@ namespace objects
// like, so we'll store the total size of the object // like, so we'll store the total size of the object
// there. A negative number indicates that the extra // there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders. // instance memory is not yet allocated to any holders.
#if PY_VERSION_HEX >= 0x02060000 result->ob_size = -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
Py_SIZE(result) =
#else
result->ob_size =
#endif
-(static_cast<int>(offsetof(instance<>,storage) + instance_size));
} }
return (PyObject*)result; return (PyObject*)result;
} }
@@ -415,7 +368,8 @@ namespace objects
}; };
static PyTypeObject class_type_object = { static PyTypeObject class_type_object = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(0) //&class_metatype_object)
0,
const_cast<char*>("Boost.Python.instance"), const_cast<char*>("Boost.Python.instance"),
offsetof(instance<>,storage), /* tp_basicsize */ offsetof(instance<>,storage), /* tp_basicsize */
1, /* tp_itemsize */ 1, /* tp_itemsize */
@@ -470,7 +424,7 @@ namespace objects
{ {
if (class_type_object.tp_dict == 0) if (class_type_object.tp_dict == 0)
{ {
Py_TYPE(&class_type_object) = incref(class_metatype().get()); class_type_object.ob_type = incref(class_metatype().get());
class_type_object.tp_base = &PyBaseObject_Type; class_type_object.tp_base = &PyBaseObject_Type;
if (PyType_Ready(&class_type_object)) if (PyType_Ready(&class_type_object))
return type_handle(); return type_handle();
@@ -482,7 +436,7 @@ namespace objects
BOOST_PYTHON_DECL void* 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, bool null_shared_ptr_only)
{ {
if (Py_TYPE(Py_TYPE(inst)) != &class_metatype_object) if (inst->ob_type->ob_type != &class_metatype_object)
return 0; return 0;
instance<>* self = reinterpret_cast<instance<>*>(inst); instance<>* self = reinterpret_cast<instance<>*>(inst);
@@ -552,12 +506,13 @@ namespace objects
// Build a tuple of the base Python type objects. If no bases // Build a tuple of the base Python type objects. If no bases
// were declared, we'll use our class_type() as the single base // were declared, we'll use our class_type() as the single base
// class. // class.
ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1)); std::size_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
handle<> bases(PyTuple_New(num_bases)); assert(num_bases <= ssize_t_max);
handle<> bases(PyTuple_New(static_cast<ssize_t>(num_bases)));
for (ssize_t i = 1; i <= num_bases; ++i) for (std::size_t i = 1; i <= num_bases; ++i)
{ {
type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]); type_handle c = (i >= num_types) ? class_type() : get_class(types[i]);
// PyTuple_SET_ITEM steals this reference // PyTuple_SET_ITEM steals this reference
PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release())); PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
} }
@@ -572,7 +527,7 @@ namespace objects
d["__doc__"] = doc; d["__doc__"] = doc;
object result = object(class_metatype())(name, bases, d); object result = object(class_metatype())(name, bases, d);
assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type)); assert(PyType_IsSubtype(result.ptr()->ob_type, &PyType_Type));
if (scope().ptr() != Py_None) if (scope().ptr() != Py_None)
scope().attr(name) = result; scope().attr(name) = result;
@@ -635,9 +590,8 @@ namespace objects
void class_base::add_static_property(char const* name, object const& fget) void class_base::add_static_property(char const* name, object const& fget)
{ {
object property( object property(
(python::detail::new_reference) (python::detail::new_reference)
PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr()) PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr()));
);
this->setattr(name, property); this->setattr(name, property);
} }
@@ -697,7 +651,7 @@ namespace objects
::PyErr_Format( ::PyErr_Format(
PyExc_TypeError PyExc_TypeError
, const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable") , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
, Py_TYPE(callable)->tp_name , callable->ob_type->tp_name
); );
throw_error_already_set(); throw_error_already_set();
@@ -727,18 +681,18 @@ namespace objects
void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size) void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
{ {
assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object); assert(self_->ob_type->ob_type == &class_metatype_object);
objects::instance<>* self = (objects::instance<>*)self_; objects::instance<>* self = (objects::instance<>*)self_;
int total_size_needed = holder_offset + holder_size; int total_size_needed = holder_offset + holder_size;
if (-Py_SIZE(self) >= total_size_needed) if (-self->ob_size >= total_size_needed)
{ {
// holder_offset should at least point into the variable-sized part // holder_offset should at least point into the variable-sized part
assert(holder_offset >= offsetof(objects::instance<>,storage)); assert(holder_offset >= offsetof(objects::instance<>,storage));
// Record the fact that the storage is occupied, noting where it starts // Record the fact that the storage is occupied, noting where it starts
Py_SIZE(self) = holder_offset; self->ob_size = holder_offset;
return (char*)self + holder_offset; return (char*)self + holder_offset;
} }
else else
@@ -752,9 +706,9 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std:
void instance_holder::deallocate(PyObject* self_, void* storage) throw() void instance_holder::deallocate(PyObject* self_, void* storage) throw()
{ {
assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object); assert(self_->ob_type->ob_type == &class_metatype_object);
objects::instance<>* self = (objects::instance<>*)self_; objects::instance<>* self = (objects::instance<>*)self_;
if (storage != (char*)self + Py_SIZE(self)) if (storage != (char*)self + self->ob_size)
{ {
PyMem_Free(storage); PyMem_Free(storage);
} }

View File

@@ -14,15 +14,11 @@
#include <boost/python/object_protocol.hpp> #include <boost/python/object_protocol.hpp>
#include <structmember.h> #include <structmember.h>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
struct enum_object struct enum_object
{ {
#if PY_VERSION_HEX >= 0x03000000
PyLongObject base_object;
#else
PyIntObject base_object; PyIntObject base_object;
#endif
PyObject* name; PyObject* name;
}; };
@@ -36,32 +32,19 @@ extern "C"
{ {
static PyObject* enum_repr(PyObject* self_) static PyObject* enum_repr(PyObject* self_)
{ {
// XXX(bhy) Potentional memory leak here since PyObject_GetAttrString returns a new reference const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast<char*>("__module__")));
// const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast<char*>("__module__")));
PyObject *mod = PyObject_GetAttrString( self_, "__module__");
enum_object* self = downcast<enum_object>(self_); enum_object* self = downcast<enum_object>(self_);
if (!self->name) if (!self->name)
{ {
return return PyString_FromFormat("%s.%s(%ld)", mod, self_->ob_type->tp_name, PyInt_AS_LONG(self_));
#if PY_VERSION_HEX >= 0x03000000
PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_));
#else
PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_));
#endif
} }
else else
{ {
PyObject* name = self->name; char* name = PyString_AsString(self->name);
if (name == 0) if (name == 0)
return 0; return 0;
return return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name);
#if PY_VERSION_HEX >= 0x03000000
PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name);
#else
PyString_FromFormat("%s.%s.%s",
PyString_AsString(mod), self_->ob_type->tp_name, PyString_AsString(name));
#endif
} }
} }
@@ -70,11 +53,7 @@ extern "C"
enum_object* self = downcast<enum_object>(self_); enum_object* self = downcast<enum_object>(self_);
if (!self->name) if (!self->name)
{ {
#if PY_VERSION_HEX >= 0x03000000
return PyLong_Type.tp_str(self_);
#else
return PyInt_Type.tp_str(self_); return PyInt_Type.tp_str(self_);
#endif
} }
else else
{ {
@@ -84,7 +63,8 @@ extern "C"
} }
static PyTypeObject enum_type_object = { static PyTypeObject enum_type_object = {
PyVarObject_HEAD_INIT(NULL, 0) // &PyType_Type PyObject_HEAD_INIT(0) // &PyType_Type
0,
const_cast<char*>("Boost.Python.enum"), const_cast<char*>("Boost.Python.enum"),
sizeof(enum_object), /* tp_basicsize */ sizeof(enum_object), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
@@ -104,9 +84,7 @@ static PyTypeObject enum_type_object = {
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT
#if PY_VERSION_HEX < 0x03000000
| Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_CHECKTYPES
#endif
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */ | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
@@ -147,12 +125,8 @@ namespace
{ {
if (enum_type_object.tp_dict == 0) if (enum_type_object.tp_dict == 0)
{ {
Py_TYPE(&enum_type_object) = incref(&PyType_Type); enum_type_object.ob_type = incref(&PyType_Type);
#if PY_VERSION_HEX >= 0x03000000
enum_type_object.tp_base = &PyLong_Type;
#else
enum_type_object.tp_base = &PyInt_Type; enum_type_object.tp_base = &PyInt_Type;
#endif
if (PyType_Ready(&enum_type_object)) if (PyType_Ready(&enum_type_object))
throw_error_already_set(); throw_error_already_set();
} }
@@ -165,16 +139,15 @@ namespace
dict d; dict d;
d["__slots__"] = tuple(); d["__slots__"] = tuple();
d["values"] = dict(); d["values"] = dict();
d["names"] = dict();
object module_name = module_prefix(); object module_name = module_prefix();
if (module_name) if (module_name)
d["__module__"] = module_name; d["__module__"] = module_name;
if (doc) if (doc)
d["__doc__"] = doc; d["__doc__"] = doc;
object result = (object(metatype))(name, make_tuple(base), d); object result = (object(metatype))(name, make_tuple(base), d);
scope().attr(name) = result; scope().attr(name) = result;
return result; return result;
@@ -194,7 +167,7 @@ enum_base::enum_base(
converter::registration& converters converter::registration& converters
= const_cast<converter::registration&>( = const_cast<converter::registration&>(
converter::registry::lookup(id)); converter::registry::lookup(id));
converters.m_class_object = downcast<PyTypeObject>(this->ptr()); converters.m_class_object = downcast<PyTypeObject>(this->ptr());
converter::registry::insert(to_python, id); converter::registry::insert(to_python, id);
converter::registry::insert(convertible, construct, id); converter::registry::insert(convertible, construct, id);
@@ -213,24 +186,23 @@ void enum_base::add_value(char const* name_, long value)
dict d = extract<dict>(this->attr("values"))(); dict d = extract<dict>(this->attr("values"))();
d[value] = x; d[value] = x;
// Set the name field in the new enum instanec // Set the name field in the new enum instanec
enum_object* p = downcast<enum_object>(x.ptr()); enum_object* p = downcast<enum_object>(x.ptr());
Py_XDECREF(p->name); Py_XDECREF(p->name);
p->name = incref(name.ptr()); p->name = incref(name.ptr());
dict names_dict = extract<dict>(this->attr("names"))();
names_dict[x.attr("name")] = x;
} }
void enum_base::export_values() void enum_base::export_values()
{ {
dict d = extract<dict>(this->attr("names"))(); dict d = extract<dict>(this->attr("values"))();
list items = d.items(); list values = d.values();
scope current; scope current;
for (unsigned i = 0, max = len(items); i < max; ++i) for (unsigned i = 0, max = len(values); i < max; ++i)
api::setattr(current, items[i][0], items[i][1]); {
api::setattr(current, object(values[i].attr("name")), values[i]);
}
} }
PyObject* enum_base::to_python(PyTypeObject* type_, long x) PyObject* enum_base::to_python(PyTypeObject* type_, long x)

View File

@@ -105,9 +105,9 @@ function::function(
} }
PyObject* p = this; PyObject* p = this;
if (Py_TYPE(&function_type) == 0) if (function_type.ob_type == 0)
{ {
Py_TYPE(&function_type) = &PyType_Type; function_type.ob_type = &PyType_Type;
::PyType_Ready(&function_type); ::PyType_Ready(&function_type);
} }
@@ -144,7 +144,7 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
if (n_keyword_actual > 0 // Keyword arguments were supplied if (n_keyword_actual > 0 // Keyword arguments were supplied
|| n_actual < min_arity) // or default keyword values are needed || n_actual < min_arity) // or default keyword values are needed
{ {
if (f->m_arg_names.is_none()) if (f->m_arg_names.ptr() == Py_None)
{ {
// this overload doesn't accept keywords // this overload doesn't accept keywords
inner_args = handle<>(); inner_args = handle<>();
@@ -166,7 +166,7 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
else else
{ {
// build a new arg tuple, will adjust its size later // build a new arg tuple, will adjust its size later
assert(max_arity <= static_cast<std::size_t>(ssize_t_max)); assert(max_arity <= ssize_t_max);
inner_args = handle<>( inner_args = handle<>(
PyTuple_New(static_cast<ssize_t>(max_arity))); PyTuple_New(static_cast<ssize_t>(max_arity)));
@@ -435,13 +435,9 @@ void function::add_to_namespace(
function* new_func = downcast<function>(attribute.ptr()); function* new_func = downcast<function>(attribute.ptr());
PyObject* dict = 0; PyObject* dict = 0;
#if PY_VERSION_HEX < 0x03000000
// Old-style class gone in Python 3
if (PyClass_Check(ns)) if (PyClass_Check(ns))
dict = ((PyClassObject*)ns)->cl_dict; dict = ((PyClassObject*)ns)->cl_dict;
else else if (PyType_Check(ns))
#endif
if (PyType_Check(ns))
dict = ((PyTypeObject*)ns)->tp_dict; dict = ((PyTypeObject*)ns)->tp_dict;
else else
dict = PyObject_GetAttrString(ns, const_cast<char*>("__dict__")); dict = PyObject_GetAttrString(ns, const_cast<char*>("__dict__"));
@@ -487,7 +483,7 @@ void function::add_to_namespace(
} }
// A function is named the first time it is added to a namespace. // A function is named the first time it is added to a namespace.
if (new_func->name().is_none()) if (new_func->name().ptr() == Py_None)
new_func->m_name = name; new_func->m_name = name;
handle<> name_space_name( handle<> name_space_name(
@@ -599,18 +595,9 @@ extern "C"
static PyObject * static PyObject *
function_descr_get(PyObject *func, PyObject *obj, PyObject *type_) function_descr_get(PyObject *func, PyObject *obj, PyObject *type_)
{ {
#if PY_VERSION_HEX >= 0x03000000
// The implement is different in Python 3 because of the removal of unbound method
if (obj == Py_None || obj == NULL) {
Py_INCREF(func);
return func;
}
return PyMethod_New(func, obj);
#else
if (obj == Py_None) if (obj == Py_None)
obj = NULL; obj = NULL;
return PyMethod_New(func, obj, type_); return PyMethod_New(func, obj, type_);
#endif
} }
static void static void
@@ -653,12 +640,8 @@ extern "C"
static PyObject* function_get_name(PyObject* op, void*) static PyObject* function_get_name(PyObject* op, void*)
{ {
function* f = downcast<function>(op); function* f = downcast<function>(op);
if (f->name().is_none()) if (f->name().ptr() == Py_None)
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_InternFromString("<unnamed Boost.Python function>");
#else
return PyString_InternFromString("<unnamed Boost.Python function>"); return PyString_InternFromString("<unnamed Boost.Python function>");
#endif
else else
return python::incref(f->name().ptr()); return python::incref(f->name().ptr());
} }
@@ -670,26 +653,11 @@ extern "C"
{ {
return python::incref(upcast<PyObject>(&PyCFunction_Type)); return python::incref(upcast<PyObject>(&PyCFunction_Type));
} }
static PyObject* function_get_module(PyObject* op, void*)
{
function* f = downcast<function>(op);
object const& ns = f->get_namespace();
if (!ns.is_none()) {
return python::incref(ns.ptr());
}
PyErr_SetString(
PyExc_AttributeError, const_cast<char*>(
"Boost.Python function __module__ unknown."));
return 0;
}
} }
static PyGetSetDef function_getsetlist[] = { static PyGetSetDef function_getsetlist[] = {
{const_cast<char*>("__name__"), (getter)function_get_name, 0, 0, 0 }, {const_cast<char*>("__name__"), (getter)function_get_name, 0, 0, 0 },
{const_cast<char*>("func_name"), (getter)function_get_name, 0, 0, 0 }, {const_cast<char*>("func_name"), (getter)function_get_name, 0, 0, 0 },
{const_cast<char*>("__module__"), (getter)function_get_module, 0, 0, 0 },
{const_cast<char*>("func_module"), (getter)function_get_module, 0, 0, 0 },
{const_cast<char*>("__class__"), (getter)function_get_class, 0, 0, 0 }, // see note above {const_cast<char*>("__class__"), (getter)function_get_class, 0, 0, 0 }, // see note above
{const_cast<char*>("__doc__"), (getter)function_get_doc, (setter)function_set_doc, 0, 0}, {const_cast<char*>("__doc__"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
{const_cast<char*>("func_doc"), (getter)function_get_doc, (setter)function_set_doc, 0, 0}, {const_cast<char*>("func_doc"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
@@ -697,7 +665,8 @@ static PyGetSetDef function_getsetlist[] = {
}; };
PyTypeObject function_type = { PyTypeObject function_type = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(0)
0,
const_cast<char*>("Boost.Python.function"), const_cast<char*>("Boost.Python.function"),
sizeof(function), sizeof(function),
0, 0,

View File

@@ -3,9 +3,6 @@
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// boost::python::make_tuple below are for gcc 4.4 -std=c++0x compatibility
// (Intel C++ 10 and 11 with -std=c++0x don't need the full qualification).
#include <boost/python/converter/registrations.hpp> #include <boost/python/converter/registrations.hpp>
#include <boost/python/object/function_doc_signature.hpp> #include <boost/python/object/function_doc_signature.hpp>
#include <boost/python/errors.hpp> #include <boost/python/errors.hpp>
@@ -15,6 +12,7 @@
#include <boost/python/detail/signature.hpp> #include <boost/python/detail/signature.hpp>
#include <vector> #include <vector>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
@@ -54,9 +52,9 @@ namespace boost { namespace python { namespace objects {
//check if the argument default values are the same //check if the argument default values are the same
bool f1_has_names = bool(f1->m_arg_names); bool f1_has_names = bool(f1->m_arg_names);
bool f2_has_names = bool(f2->m_arg_names); bool f2_has_names = bool(f2->m_arg_names);
if ( (f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1]) if ( f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1]
|| (f1_has_names && !f2_has_names) || f1_has_names && !f2_has_names
|| (!f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object()) || !f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object()
) )
return false; return false;
} }
@@ -230,7 +228,7 @@ namespace boost { namespace python { namespace objects {
{ {
return str( return str(
"%s %s(%s%s%s%s)" "%s %s(%s%s%s%s)"
% boost::python::make_tuple // workaround, see top % make_tuple
( ret_type ( ret_type
, f->m_name , f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads)) , str(",").join(formal_params.slice(0,arity-n_overloads))
@@ -241,7 +239,7 @@ namespace boost { namespace python { namespace objects {
}else{ }else{
return str( return str(
"%s(%s%s%s%s) -> %s" "%s(%s%s%s%s) -> %s"
% boost::python::make_tuple // workaround, see top % make_tuple
( f->m_name ( f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads)) , str(",").join(formal_params.slice(0,arity-n_overloads))
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str() , n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
@@ -253,7 +251,7 @@ namespace boost { namespace python { namespace objects {
return str( return str(
"%s %s(%s%s%s%s) %s" "%s %s(%s%s%s%s) %s"
% boost::python::make_tuple // workaround, see top % make_tuple
( cpp_types?ret_type:str("") ( cpp_types?ret_type:str("")
, f->m_name , f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads)) , str(",").join(formal_params.slice(0,arity-n_overloads))

View File

@@ -10,7 +10,7 @@
#endif #endif
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp> #include <boost/graph/reverse_graph.hpp>
#include <boost/property_map/property_map.hpp> #include <boost/property_map.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/integer_traits.hpp> #include <boost/integer_traits.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>

View File

@@ -36,7 +36,8 @@ extern "C"
} }
PyTypeObject life_support_type = { PyTypeObject life_support_type = {
PyVarObject_HEAD_INIT(NULL, 0)//(&PyType_Type) PyObject_HEAD_INIT(0)//(&PyType_Type)
0,
const_cast<char*>("Boost.Python.life_support"), const_cast<char*>("Boost.Python.life_support"),
sizeof(life_support), sizeof(life_support),
0, 0,
@@ -91,9 +92,9 @@ PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)
if (nurse == Py_None || nurse == patient) if (nurse == Py_None || nurse == patient)
return nurse; return nurse;
if (Py_TYPE(&life_support_type) == 0) if (life_support_type.ob_type == 0)
{ {
Py_TYPE(&life_support_type) = &PyType_Type; life_support_type.ob_type = &PyType_Type;
PyType_Ready(&life_support_type); PyType_Ready(&life_support_type);
} }

View File

@@ -38,21 +38,21 @@ namespace {
} }
object getinitargs = getattr(instance_obj, "__getinitargs__", none); object getinitargs = getattr(instance_obj, "__getinitargs__", none);
tuple initargs; tuple initargs;
if (!getinitargs.is_none()) { if (getinitargs.ptr() != none.ptr()) {
initargs = tuple(getinitargs()); initargs = tuple(getinitargs());
} }
result.append(initargs); result.append(initargs);
object getstate = getattr(instance_obj, "__getstate__", none); object getstate = getattr(instance_obj, "__getstate__", none);
object instance_dict = getattr(instance_obj, "__dict__", none); object instance_dict = getattr(instance_obj, "__dict__", none);
long len_instance_dict = 0; long len_instance_dict = 0;
if (!instance_dict.is_none()) { if (instance_dict.ptr() != none.ptr()) {
len_instance_dict = len(instance_dict); len_instance_dict = len(instance_dict);
} }
if (!getstate.is_none()) { if (getstate.ptr() != none.ptr()) {
if (len_instance_dict > 0) { if (len_instance_dict > 0) {
object getstate_manages_dict = getattr( object getstate_manages_dict = getattr(
instance_obj, "__getstate_manages_dict__", none); instance_obj, "__getstate_manages_dict__", none);
if (getstate_manages_dict.is_none()) { if (getstate_manages_dict.ptr() == none.ptr()) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"Incomplete pickle support" "Incomplete pickle support"
" (__getstate_manages_dict__ not set)"); " (__getstate_manages_dict__ not set)");

View File

@@ -38,13 +38,7 @@ BOOST_PYTHON_DECL object operator op(object const& l, object const& r) \
BOOST_PYTHON_BINARY_OPERATOR(+, Add) BOOST_PYTHON_BINARY_OPERATOR(+, Add)
BOOST_PYTHON_BINARY_OPERATOR(-, Subtract) BOOST_PYTHON_BINARY_OPERATOR(-, Subtract)
BOOST_PYTHON_BINARY_OPERATOR(*, Multiply) BOOST_PYTHON_BINARY_OPERATOR(*, Multiply)
#if PY_VERSION_HEX >= 0x03000000
// We choose FloorDivide instead of TrueDivide to keep the semantic
// conform with C/C++'s '/' operator
BOOST_PYTHON_BINARY_OPERATOR(/, FloorDivide)
#else
BOOST_PYTHON_BINARY_OPERATOR(/, Divide) BOOST_PYTHON_BINARY_OPERATOR(/, Divide)
#endif
BOOST_PYTHON_BINARY_OPERATOR(%, Remainder) BOOST_PYTHON_BINARY_OPERATOR(%, Remainder)
BOOST_PYTHON_BINARY_OPERATOR(<<, Lshift) BOOST_PYTHON_BINARY_OPERATOR(<<, Lshift)
BOOST_PYTHON_BINARY_OPERATOR(>>, Rshift) BOOST_PYTHON_BINARY_OPERATOR(>>, Rshift)
@@ -64,12 +58,7 @@ BOOST_PYTHON_DECL object& operator op##=(object& l, object const& r) \
BOOST_PYTHON_INPLACE_OPERATOR(+, Add) BOOST_PYTHON_INPLACE_OPERATOR(+, Add)
BOOST_PYTHON_INPLACE_OPERATOR(-, Subtract) BOOST_PYTHON_INPLACE_OPERATOR(-, Subtract)
BOOST_PYTHON_INPLACE_OPERATOR(*, Multiply) BOOST_PYTHON_INPLACE_OPERATOR(*, Multiply)
#if PY_VERSION_HEX >= 0x03000000
// Same reason as above for choosing FloorDivide instead of TrueDivide
BOOST_PYTHON_INPLACE_OPERATOR(/, FloorDivide)
#else
BOOST_PYTHON_INPLACE_OPERATOR(/, Divide) BOOST_PYTHON_INPLACE_OPERATOR(/, Divide)
#endif
BOOST_PYTHON_INPLACE_OPERATOR(%, Remainder) BOOST_PYTHON_INPLACE_OPERATOR(%, Remainder)
BOOST_PYTHON_INPLACE_OPERATOR(<<, Lshift) BOOST_PYTHON_INPLACE_OPERATOR(<<, Lshift)
BOOST_PYTHON_INPLACE_OPERATOR(>>, Rshift) BOOST_PYTHON_INPLACE_OPERATOR(>>, Rshift)

View File

@@ -103,7 +103,6 @@ namespace // slicing code copied directly out of the Python implementation
static PyObject * static PyObject *
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */ apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
{ {
#if PY_VERSION_HEX < 0x03000000
PyTypeObject *tp = u->ob_type; PyTypeObject *tp = u->ob_type;
PySequenceMethods *sq = tp->tp_as_sequence; PySequenceMethods *sq = tp->tp_as_sequence;
@@ -115,9 +114,7 @@ namespace // slicing code copied directly out of the Python implementation
return NULL; return NULL;
return PySequence_GetSlice(u, ilow, ihigh); return PySequence_GetSlice(u, ilow, ihigh);
} }
else else {
#endif
{
PyObject *slice = PySlice_New(v, w, NULL); PyObject *slice = PySlice_New(v, w, NULL);
if (slice != NULL) { if (slice != NULL) {
PyObject *res = PyObject_GetItem(u, slice); PyObject *res = PyObject_GetItem(u, slice);
@@ -133,7 +130,6 @@ namespace // slicing code copied directly out of the Python implementation
assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x) assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
/* u[v:w] = x */ /* u[v:w] = x */
{ {
#if PY_VERSION_HEX < 0x03000000
PyTypeObject *tp = u->ob_type; PyTypeObject *tp = u->ob_type;
PySequenceMethods *sq = tp->tp_as_sequence; PySequenceMethods *sq = tp->tp_as_sequence;
@@ -148,9 +144,7 @@ namespace // slicing code copied directly out of the Python implementation
else else
return PySequence_SetSlice(u, ilow, ihigh, x); return PySequence_SetSlice(u, ilow, ihigh, x);
} }
else else {
#endif
{
PyObject *slice = PySlice_New(v, w, NULL); PyObject *slice = PySlice_New(v, w, NULL);
if (slice != NULL) { if (slice != NULL) {
int res; int res;

View File

@@ -10,40 +10,23 @@ namespace boost { namespace python { namespace detail {
detail::new_reference str_base::call(object const& arg_) detail::new_reference str_base::call(object const& arg_)
{ {
return (detail::new_reference)PyObject_CallFunction( return (detail::new_reference)PyObject_CallFunction(
#if PY_VERSION_HEX >= 0x03000000 (PyObject*)&PyString_Type, const_cast<char*>("(O)"),
(PyObject*)&PyUnicode_Type,
#else
(PyObject*)&PyString_Type,
#endif
const_cast<char*>("(O)"),
arg_.ptr()); arg_.ptr());
} }
str_base::str_base() str_base::str_base()
: object(detail::new_reference( : object(detail::new_reference(::PyString_FromString("")))
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromString("")
#else
::PyString_FromString("")
#endif
))
{} {}
str_base::str_base(const char* s) str_base::str_base(const char* s)
: object(detail::new_reference( : object(detail::new_reference(::PyString_FromString(s)))
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromString(s)
#else
::PyString_FromString(s)
#endif
))
{} {}
namespace { namespace {
ssize_t str_size_as_py_ssize_t(std::size_t n) ssize_t str_size_as_py_ssize_t(std::size_t n)
{ {
if (n > static_cast<std::size_t>(ssize_t_max)) if (n > ssize_t_max)
{ {
throw std::range_error("str size > ssize_t_max"); throw std::range_error("str size > ssize_t_max");
} }
@@ -55,12 +38,9 @@ namespace {
str_base::str_base(char const* start, char const* finish) str_base::str_base(char const* start, char const* finish)
: object( : object(
detail::new_reference( detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000 ::PyString_FromStringAndSize(
::PyUnicode_FromStringAndSize start, str_size_as_py_ssize_t(finish - start)
#else )
::PyString_FromStringAndSize
#endif
(start, str_size_as_py_ssize_t(finish - start))
) )
) )
{} {}
@@ -68,12 +48,9 @@ str_base::str_base(char const* start, char const* finish)
str_base::str_base(char const* start, std::size_t length) // new str str_base::str_base(char const* start, std::size_t length) // new str
: object( : object(
detail::new_reference( detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000 ::PyString_FromStringAndSize(
::PyUnicode_FromStringAndSize start, str_size_as_py_ssize_t(length)
#else )
::PyString_FromStringAndSize
#endif
( start, str_size_as_py_ssize_t(length) )
) )
) )
{} {}
@@ -115,7 +92,6 @@ long str_base::count(object_cref sub, object_cref start, object_cref end) const
return extract<long>(this->attr("count")(sub,start,end)); return extract<long>(this->attr("count")(sub,start,end));
} }
#if PY_VERSION_HEX < 0x03000000
object str_base::decode() const object str_base::decode() const
{ {
return this->attr("decode")(); return this->attr("decode")();
@@ -130,7 +106,6 @@ object str_base::decode(object_cref encoding, object_cref errors) const
{ {
return this->attr("decode")(encoding,errors); return this->attr("decode")(encoding,errors);
} }
#endif
object str_base::encode() const object str_base::encode() const
{ {
@@ -147,16 +122,9 @@ object str_base::encode(object_cref encoding, object_cref errors) const
return this->attr("encode")(encoding,errors); return this->attr("encode")(encoding,errors);
} }
#if PY_VERSION_HEX >= 0x03000000
#define _BOOST_PYTHON_ASLONG PyLong_AsLong
#else
#define _BOOST_PYTHON_ASLONG PyInt_AsLong
#endif
bool str_base::endswith(object_cref suffix) const bool str_base::endswith(object_cref suffix) const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix).ptr()); bool result = PyInt_AsLong(this->attr("endswith")(suffix).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -167,7 +135,7 @@ BOOST_PYTHON_DEFINE_STR_METHOD(expandtabs, 1)
long str_base::find(object_cref sub) const long str_base::find(object_cref sub) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub).ptr()); long result = PyInt_AsLong(this->attr("find")(sub).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -175,7 +143,7 @@ long str_base::find(object_cref sub) const
long str_base::find(object_cref sub, object_cref start) const long str_base::find(object_cref sub, object_cref start) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start).ptr()); long result = PyInt_AsLong(this->attr("find")(sub,start).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -183,7 +151,7 @@ long str_base::find(object_cref sub, object_cref start) const
long str_base::find(object_cref sub, object_cref start, object_cref end) const long str_base::find(object_cref sub, object_cref start, object_cref end) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start,end).ptr()); long result = PyInt_AsLong(this->attr("find")(sub,start,end).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -191,7 +159,7 @@ long str_base::find(object_cref sub, object_cref start, object_cref end) const
long str_base::index(object_cref sub) const long str_base::index(object_cref sub) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub).ptr()); long result = PyInt_AsLong(this->attr("index")(sub).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -199,7 +167,7 @@ long str_base::index(object_cref sub) const
long str_base::index(object_cref sub, object_cref start) const long str_base::index(object_cref sub, object_cref start) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start).ptr()); long result = PyInt_AsLong(this->attr("index")(sub,start).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -207,7 +175,7 @@ long str_base::index(object_cref sub, object_cref start) const
long str_base::index(object_cref sub, object_cref start, object_cref end) const long str_base::index(object_cref sub, object_cref start, object_cref end) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start,end).ptr()); long result = PyInt_AsLong(this->attr("index")(sub,start,end).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -215,7 +183,7 @@ long str_base::index(object_cref sub, object_cref start, object_cref end) const
bool str_base::isalnum() const bool str_base::isalnum() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("isalnum")().ptr()); bool result = PyInt_AsLong(this->attr("isalnum")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -223,7 +191,7 @@ bool str_base::isalnum() const
bool str_base::isalpha() const bool str_base::isalpha() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("isalpha")().ptr()); bool result = PyInt_AsLong(this->attr("isalpha")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -231,7 +199,7 @@ bool str_base::isalpha() const
bool str_base::isdigit() const bool str_base::isdigit() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("isdigit")().ptr()); bool result = PyInt_AsLong(this->attr("isdigit")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -239,7 +207,7 @@ bool str_base::isdigit() const
bool str_base::islower() const bool str_base::islower() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("islower")().ptr()); bool result = PyInt_AsLong(this->attr("islower")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -247,7 +215,7 @@ bool str_base::islower() const
bool str_base::isspace() const bool str_base::isspace() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("isspace")().ptr()); bool result = PyInt_AsLong(this->attr("isspace")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -255,7 +223,7 @@ bool str_base::isspace() const
bool str_base::istitle() const bool str_base::istitle() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("istitle")().ptr()); bool result = PyInt_AsLong(this->attr("istitle")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -263,7 +231,7 @@ bool str_base::istitle() const
bool str_base::isupper() const bool str_base::isupper() const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("isupper")().ptr()); bool result = PyInt_AsLong(this->attr("isupper")().ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -278,7 +246,7 @@ BOOST_PYTHON_DEFINE_STR_METHOD(replace, 3)
long str_base::rfind(object_cref sub) const long str_base::rfind(object_cref sub) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub).ptr()); long result = PyInt_AsLong(this->attr("rfind")(sub).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -286,7 +254,7 @@ long str_base::rfind(object_cref sub) const
long str_base::rfind(object_cref sub, object_cref start) const long str_base::rfind(object_cref sub, object_cref start) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start).ptr()); long result = PyInt_AsLong(this->attr("rfind")(sub,start).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -294,7 +262,7 @@ long str_base::rfind(object_cref sub, object_cref start) const
long str_base::rfind(object_cref sub, object_cref start, object_cref end) const long str_base::rfind(object_cref sub, object_cref start, object_cref end) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start,end).ptr()); long result = PyInt_AsLong(this->attr("rfind")(sub,start,end).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -302,7 +270,7 @@ long str_base::rfind(object_cref sub, object_cref start, object_cref end) const
long str_base::rindex(object_cref sub) const long str_base::rindex(object_cref sub) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub).ptr()); long result = PyInt_AsLong(this->attr("rindex")(sub).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -310,7 +278,7 @@ long str_base::rindex(object_cref sub) const
long str_base::rindex(object_cref sub, object_cref start) const long str_base::rindex(object_cref sub, object_cref start) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start).ptr()); long result = PyInt_AsLong(this->attr("rindex")(sub,start).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -318,7 +286,7 @@ long str_base::rindex(object_cref sub, object_cref start) const
long str_base::rindex(object_cref sub, object_cref start, object_cref end) const long str_base::rindex(object_cref sub, object_cref start, object_cref end) const
{ {
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start,end).ptr()); long result = PyInt_AsLong(this->attr("rindex")(sub,start,end).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -354,7 +322,7 @@ list str_base::splitlines(object_cref keepends) const
bool str_base::startswith(object_cref prefix) const bool str_base::startswith(object_cref prefix) const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix).ptr()); bool result = PyInt_AsLong(this->attr("startswith")(prefix).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -362,7 +330,7 @@ bool str_base::startswith(object_cref prefix) const
bool str_base::startswith(object_cref prefix, object_cref start) const bool str_base::startswith(object_cref prefix, object_cref start) const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start).ptr()); bool result = PyInt_AsLong(this->attr("startswith")(prefix,start).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
@@ -370,14 +338,12 @@ bool str_base::startswith(object_cref prefix, object_cref start) const
bool str_base::startswith(object_cref prefix, object_cref start, object_cref end) const bool str_base::startswith(object_cref prefix, object_cref start, object_cref end) const
{ {
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start,end).ptr()); bool result = PyInt_AsLong(this->attr("startswith")(prefix,start,end).ptr());
if (PyErr_Occurred()) if (PyErr_Occurred())
throw_error_already_set(); throw_error_already_set();
return result; return result;
} }
#undef _BOOST_PYTHON_ASLONG
BOOST_PYTHON_DEFINE_STR_METHOD(strip, 0) BOOST_PYTHON_DEFINE_STR_METHOD(strip, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(swapcase, 0) BOOST_PYTHON_DEFINE_STR_METHOD(swapcase, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(title, 0) BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
@@ -391,12 +357,7 @@ static struct register_str_pytype_ptr
{ {
const_cast<converter::registration &>( const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::str>()) converter::registry::lookup(boost::python::type_id<boost::python::str>())
) ).m_class_object = &PyString_Type;
#if PY_VERSION_HEX >= 0x03000000
.m_class_object = &PyUnicode_Type;
#else
.m_class_object = &PyString_Type;
#endif
} }
}register_str_pytype_ptr_; }register_str_pytype_ptr_;

View File

@@ -37,13 +37,6 @@ rule py-compile-fail ( sources * )
return [ compile-fail $(sources) /boost/python//boost_python ] ; return [ compile-fail $(sources) /boost/python//boost_python ] ;
} }
rule require-windows ( properties * )
{
if ! <target-os>windows in $(properties)
{
return <build>no ;
}
}
test-suite python test-suite python
: :
@@ -82,17 +75,13 @@ bpl-test crossmod_exception
[ bpl-test return_arg ] [ bpl-test return_arg ]
[ bpl-test staticmethod ] [ bpl-test staticmethod ]
[ bpl-test shared_ptr ] [ bpl-test shared_ptr ]
[ bpl-test enable_shared_from_this ]
[ bpl-test andreas_beyer ] [ bpl-test andreas_beyer ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr
: polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp
]
[ bpl-test polymorphism ] [ bpl-test polymorphism ]
[ bpl-test polymorphism2 ] [ bpl-test polymorphism2 ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr ]
[ bpl-test auto_ptr ] [ bpl-test auto_ptr ]
[ bpl-test minimal ] [ bpl-test minimal ]
@@ -191,9 +180,6 @@ bpl-test crossmod_opaque
# bpl-test bienstman5 ; # bpl-test bienstman5 ;
# } # }
[ bpl-test calling_conventions : : <conditional>@require-windows ]
[ bpl-test calling_conventions_mf : : <conditional>@require-windows ]
# --- unit tests of library components --- # --- unit tests of library components ---
[ compile indirect_traits_test.cpp ] [ compile indirect_traits_test.cpp ]

View File

@@ -48,11 +48,7 @@ struct AFromPython
static void* convertible(PyObject* obj_ptr) static void* convertible(PyObject* obj_ptr)
{ {
#if PY_VERSION_HEX >= 0x03000000
if (!PyLong_Check(obj_ptr)) return 0;
#else
if (!PyInt_Check(obj_ptr)) return 0; if (!PyInt_Check(obj_ptr)) return 0;
#endif
return obj_ptr; return obj_ptr;
} }
@@ -64,11 +60,7 @@ struct AFromPython
(boost::python::converter::rvalue_from_python_storage< A >*) (boost::python::converter::rvalue_from_python_storage< A >*)
data)-> storage.bytes; data)-> storage.bytes;
#if PY_VERSION_HEX >= 0x03000000
new (storage) A((int)PyLong_AsLong(obj_ptr));
#else
new (storage) A((int)PyInt_AsLong(obj_ptr)); new (storage) A((int)PyInt_AsLong(obj_ptr));
#endif
data->convertible = storage; data->convertible = storage;
} }
}; };

View File

@@ -1,158 +0,0 @@
//
// adapted from bind_stdcall_test.cpp - test for bind.hpp + __stdcall (free functions)
// The purpose of this simple test is to determine if a function can be
// called from Python with the various existing calling conventions
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// 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)
//
#if !defined(TEST_INCLUDE_RECURSION)
#define TEST_INCLUDE_RECURSION
//------------------------------------------------------------------------------
// this section is the main body of the test extension module
#define BOOST_PYTHON_ENABLE_CDECL
#define BOOST_PYTHON_ENABLE_STDCALL
#define BOOST_PYTHON_ENABLE_FASTCALL
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/python.hpp>
using namespace boost::python;
// first define test functions for every calling convention
#define TEST_DECLARE_FUNCTIONS
#define TESTED_CALLING_CONVENTION __cdecl
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __stdcall
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __fastcall
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#undef TEST_DECLARE_FUNCTIONS
// then create a module wrapping the defined functions for every calling convention
BOOST_PYTHON_MODULE( calling_conventions_ext )
{
#define TEST_WRAP_FUNCTIONS
#define TESTED_CALLING_CONVENTION __cdecl
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __stdcall
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __fastcall
#include "calling_conventions.cpp"
#undef TESTED_CALLING_CONVENTION
#undef TEST_WRAP_FUNCTIONS
}
#else // !defined(TEST_INCLUDE_RECURSION)
//------------------------------------------------------------------------------
// this section defines the functions to be wrapped
# if defined(TEST_DECLARE_FUNCTIONS)
# if !defined(TESTED_CALLING_CONVENTION)
# error "One calling convention must be defined"
# endif // !defined(TESTED_CALLING_CONVENTION)
namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) {
long TESTED_CALLING_CONVENTION f_0()
{
return 17041L;
}
long TESTED_CALLING_CONVENTION f_1(long a)
{
return a;
}
long TESTED_CALLING_CONVENTION f_2(long a, long b)
{
return a + 10 * b;
}
long TESTED_CALLING_CONVENTION f_3(long a, long b, long c)
{
return a + 10 * b + 100 * c;
}
long TESTED_CALLING_CONVENTION f_4(long a, long b, long c, long d)
{
return a + 10 * b + 100 * c + 1000 * d;
}
long TESTED_CALLING_CONVENTION f_5(long a, long b, long c, long d, long e)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}
long TESTED_CALLING_CONVENTION f_6(long a, long b, long c, long d, long e, long f)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}
long TESTED_CALLING_CONVENTION f_7(long a, long b, long c, long d, long e, long f, long g)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
}
long TESTED_CALLING_CONVENTION f_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h;
}
long TESTED_CALLING_CONVENTION f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i;
}
} // namespace test##TESTED_CALLING_CONVENTION
# endif // defined(TEST_DECLARE_FUNCTIONS)
//------------------------------------------------------------------------------
// this section wraps the functions
# if defined(TEST_WRAP_FUNCTIONS)
# if !defined(TESTED_CALLING_CONVENTION)
# error "One calling convention must be defined"
# endif // !defined(TESTED_CALLING_CONVENTION)
def("f_0" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_0);
def("f_1" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_1);
def("f_2" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_2);
def("f_3" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_3);
def("f_4" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_4);
def("f_5" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_5);
def("f_6" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_6);
def("f_7" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_7);
def("f_8" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_8);
def("f_9" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_9);
# endif // defined(TEST_WRAP_FUNCTIONS)
#endif // !defined(TEST_INCLUDE_RECURSION)

View File

@@ -1,81 +0,0 @@
# Copyright Nicolas Lelong, 2010. 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 calling_conventions_ext import *
>>> f_0__cdecl()
17041
>>> f_1__cdecl(1)
1
>>> f_2__cdecl(1, 2)
21
>>> f_3__cdecl(1, 2, 3)
321
>>> f_4__cdecl(1, 2, 3, 4)
4321
>>> f_5__cdecl(1, 2, 3, 4, 5)
54321
>>> f_6__cdecl(1, 2, 3, 4, 5, 6)
654321
>>> f_7__cdecl(1, 2, 3, 4, 5, 6, 7)
7654321
>>> f_8__cdecl(1, 2, 3, 4, 5, 6, 7, 8)
87654321
>>> f_9__cdecl(1, 2, 3, 4, 5, 6, 7, 8, 9)
987654321
>>> f_0__stdcall()
17041
>>> f_1__stdcall(1)
1
>>> f_2__stdcall(1, 2)
21
>>> f_3__stdcall(1, 2, 3)
321
>>> f_4__stdcall(1, 2, 3, 4)
4321
>>> f_5__stdcall(1, 2, 3, 4, 5)
54321
>>> f_6__stdcall(1, 2, 3, 4, 5, 6)
654321
>>> f_7__stdcall(1, 2, 3, 4, 5, 6, 7)
7654321
>>> f_8__stdcall(1, 2, 3, 4, 5, 6, 7, 8)
87654321
>>> f_9__stdcall(1, 2, 3, 4, 5, 6, 7, 8, 9)
987654321
>>> f_0__fastcall()
17041
>>> f_1__fastcall(1)
1
>>> f_2__fastcall(1, 2)
21
>>> f_3__fastcall(1, 2, 3)
321
>>> f_4__fastcall(1, 2, 3, 4)
4321
>>> f_5__fastcall(1, 2, 3, 4, 5)
54321
>>> f_6__fastcall(1, 2, 3, 4, 5, 6)
654321
>>> f_7__fastcall(1, 2, 3, 4, 5, 6, 7)
7654321
>>> f_8__fastcall(1, 2, 3, 4, 5, 6, 7, 8)
87654321
>>> f_9__fastcall(1, 2, 3, 4, 5, 6, 7, 8, 9)
987654321
"""
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,159 +0,0 @@
//
// adapted from bind_stdcall_mf_test.cpp - test for bind.hpp + __stdcall (free functions)
// The purpose of this simple test is to determine if a function can be
// called from Python with the various existing calling conventions
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// 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)
//
#if !defined(TEST_INCLUDE_RECURSION)
#define TEST_INCLUDE_RECURSION
//------------------------------------------------------------------------------
// this section is the main body of the test extension module
#define BOOST_PYTHON_ENABLE_CDECL
#define BOOST_PYTHON_ENABLE_STDCALL
#define BOOST_PYTHON_ENABLE_FASTCALL
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/python.hpp>
using namespace boost::python;
// first define test functions for every calling convention
#define TEST_DECLARE_FUNCTIONS
#define TESTED_CALLING_CONVENTION __cdecl
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __stdcall
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __fastcall
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#undef TEST_DECLARE_FUNCTIONS
// then create a module wrapping the defined functions for every calling convention
BOOST_PYTHON_MODULE( calling_conventions_mf_ext )
{
#define TEST_WRAP_FUNCTIONS
#define TESTED_CALLING_CONVENTION __cdecl
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __stdcall
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#define TESTED_CALLING_CONVENTION __fastcall
#include "calling_conventions_mf.cpp"
#undef TESTED_CALLING_CONVENTION
#undef TEST_WRAP_FUNCTIONS
}
#else // !defined(TEST_INCLUDE_RECURSION)
//------------------------------------------------------------------------------
// this section defines the functions to be wrapped
# if defined(TEST_DECLARE_FUNCTIONS)
# if !defined(TESTED_CALLING_CONVENTION)
# error "One calling convention must be defined"
# endif // !defined(TESTED_CALLING_CONVENTION)
namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) {
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
void TESTED_CALLING_CONVENTION f0() { f1(17); }
void TESTED_CALLING_CONVENTION g0() const { g1(17); }
void TESTED_CALLING_CONVENTION f1(int a1) { hash = (hash * 17041 + a1) % 32768; }
void TESTED_CALLING_CONVENTION g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; }
void TESTED_CALLING_CONVENTION f2(int a1, int a2) { f1(a1); f1(a2); }
void TESTED_CALLING_CONVENTION g2(int a1, int a2) const { g1(a1); g1(a2); }
void TESTED_CALLING_CONVENTION f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); }
void TESTED_CALLING_CONVENTION g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); }
void TESTED_CALLING_CONVENTION f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); }
void TESTED_CALLING_CONVENTION g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); }
void TESTED_CALLING_CONVENTION f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); }
void TESTED_CALLING_CONVENTION g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); }
void TESTED_CALLING_CONVENTION f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); }
void TESTED_CALLING_CONVENTION g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); }
void TESTED_CALLING_CONVENTION f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); }
void TESTED_CALLING_CONVENTION g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); }
void TESTED_CALLING_CONVENTION f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); }
void TESTED_CALLING_CONVENTION g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); }
};
} // namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)
# endif // defined(TEST_DECLARE_FUNCTIONS)
//------------------------------------------------------------------------------
// this section wraps the functions
# if defined(TEST_WRAP_FUNCTIONS)
# if !defined(TESTED_CALLING_CONVENTION)
# error "One calling convention must be defined"
# endif // !defined(TESTED_CALLING_CONVENTION)
{
typedef BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::X X;
class_<X>("X" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION))
.def("f0", &X::f0)
.def("g0", &X::g0)
.def("f1", &X::f1)
.def("g1", &X::g1)
.def("f2", &X::f2)
.def("g2", &X::g2)
.def("f3", &X::f3)
.def("g3", &X::g3)
.def("f4", &X::f4)
.def("g4", &X::g4)
.def("f5", &X::f5)
.def("g5", &X::g5)
.def("f6", &X::f6)
.def("g6", &X::g6)
.def("f7", &X::f7)
.def("g7", &X::g7)
.def("f8", &X::f8)
.def("g8", &X::g8)
.def_readonly("hash", &X::hash)
;
}
# endif // defined(TEST_WRAP_FUNCTIONS)
#endif // !defined(TEST_INCLUDE_RECURSION)

View File

@@ -1,84 +0,0 @@
# Copyright Nicolas Lelong, 2010. 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 calling_conventions_mf_ext import *
>>> x = X__cdecl()
>>> x.f0()
>>> x.g0()
>>> x.f1(1)
>>> x.g1(1)
>>> x.f2(1, 2)
>>> x.g2(1, 2)
>>> x.f3(1, 2, 3)
>>> x.g3(1, 2, 3)
>>> x.f4(1, 2, 3, 4)
>>> x.g4(1, 2, 3, 4)
>>> x.f5(1, 2, 3, 4, 5)
>>> x.g5(1, 2, 3, 4, 5)
>>> x.f6(1, 2, 3, 4, 5, 6)
>>> x.g6(1, 2, 3, 4, 5, 6)
>>> x.f7(1, 2, 3, 4, 5, 6, 7)
>>> x.g7(1, 2, 3, 4, 5, 6, 7)
>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.hash
2155
>>> x = X__stdcall()
>>> x.f0()
>>> x.g0()
>>> x.f1(1)
>>> x.g1(1)
>>> x.f2(1, 2)
>>> x.g2(1, 2)
>>> x.f3(1, 2, 3)
>>> x.g3(1, 2, 3)
>>> x.f4(1, 2, 3, 4)
>>> x.g4(1, 2, 3, 4)
>>> x.f5(1, 2, 3, 4, 5)
>>> x.g5(1, 2, 3, 4, 5)
>>> x.f6(1, 2, 3, 4, 5, 6)
>>> x.g6(1, 2, 3, 4, 5, 6)
>>> x.f7(1, 2, 3, 4, 5, 6, 7)
>>> x.g7(1, 2, 3, 4, 5, 6, 7)
>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.hash
2155
>>> x = X__fastcall()
>>> x.f0()
>>> x.g0()
>>> x.f1(1)
>>> x.g1(1)
>>> x.f2(1, 2)
>>> x.g2(1, 2)
>>> x.f3(1, 2, 3)
>>> x.g3(1, 2, 3)
>>> x.f4(1, 2, 3, 4)
>>> x.g4(1, 2, 3, 4)
>>> x.f5(1, 2, 3, 4, 5)
>>> x.g5(1, 2, 3, 4, 5)
>>> x.f6(1, 2, 3, 4, 5, 6)
>>> x.g6(1, 2, 3, 4, 5, 6)
>>> x.f7(1, 2, 3, 4, 5, 6, 7)
>>> x.g7(1, 2, 3, 4, 5, 6, 7)
>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8)
>>> x.hash
2155
"""
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,4 +1,4 @@
# -*- coding: latin-1 -*- # -*- coding: iso-latin-1 -*-
# Copyright Gottfried Ganßauge 2006. # Copyright Gottfried Ganßauge 2006.
# Distributed under the Boost Software License, Version 1.0. (See # Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at # accompanying file LICENSE_1_0.txt or copy at

View File

@@ -2,6 +2,13 @@
# Software License, Version 1.0. (See accompanying # Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
""" """
# Use builtin True/False when available:
>>> try:
... assert(True == 1)
... except:
... True = 1
... False = 0
>>> from defaults_ext import * >>> from defaults_ext import *
>>> bar(1) >>> bar(1)
'int(1); char(D); string(default); double(0.0); ' 'int(1); char(D); string(default); double(0.0); '

View File

@@ -22,10 +22,6 @@ struct foo
*kills++ = n; *kills++ = n;
} }
int n; int n;
// This used to cause compiler errors with MSVC 9.0.
foo& operator~();
foo& T();
}; };
void assert_destructions(int n) void assert_destructions(int n)

View File

@@ -20,7 +20,7 @@
[(1, {'key2': 'value2'}), ('key1', 'value1')] [(1, {'key2': 'value2'}), ('key1', 'value1')]
>>> print dict_from_sequence([(1,1),(2,2),(3,3)]) >>> print dict_from_sequence([(1,1),(2,2),(3,3)])
{1: 1, 2: 2, 3: 3} {1: 1, 2: 2, 3: 3}
>>> test_templates(printer) #doctest: +NORMALIZE_WHITESPACE >>> test_templates(printer)
a test string a test string
13 13
None None

View File

@@ -1,48 +0,0 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/def.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include "test_class.hpp"
#include <memory>
using namespace boost::python;
using boost::shared_ptr;
class Test;
typedef shared_ptr<Test> TestPtr;
class Test : public boost::enable_shared_from_this<Test> {
public:
static TestPtr construct() {
return TestPtr(new Test);
}
void act() {
TestPtr kungFuDeathGrip(shared_from_this());
}
void take(TestPtr t) {
}
};
BOOST_PYTHON_MODULE(enable_shared_from_this_ext)
{
class_<Test, TestPtr, boost::noncopyable>("Test")
.def("construct", &Test::construct).staticmethod("construct")
.def("act", &Test::act)
.def("take", &Test::take)
;
}
#include "module_tail.cpp"

View File

@@ -1,26 +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 enable_shared_from_this_ext import *
>>> x = Test.construct()
>>> x.take(x)
>>> x.act()
'''
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

@@ -12,7 +12,7 @@
#endif #endif
using namespace boost::python; using namespace boost::python;
enum color { red = 1, green = 2, blue = 4, blood = 1 }; enum color { red = 1, green = 2, blue = 4 };
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
namespace boost // Pro7 has a hard time detecting enums namespace boost // Pro7 has a hard time detecting enums
@@ -34,7 +34,6 @@ BOOST_PYTHON_MODULE(enum_ext)
.value("red", red) .value("red", red)
.value("green", green) .value("green", green)
.value("blue", blue) .value("blue", blue)
.value("blood", blood)
.export_values() .export_values()
; ;

View File

@@ -4,8 +4,8 @@
''' '''
>>> from enum_ext import * >>> from enum_ext import *
>>> identity(color.red) # in case of duplicated enums it always take the last enum >>> identity(color.red)
enum_ext.color.blood enum_ext.color.red
>>> identity(color.green) >>> identity(color.green)
enum_ext.color.green enum_ext.color.green
@@ -13,8 +13,8 @@ enum_ext.color.green
>>> identity(color.blue) >>> identity(color.blue)
enum_ext.color.blue enum_ext.color.blue
>>> identity(color(1)) # in case of duplicated enums it always take the last enum >>> identity(color(1))
enum_ext.color.blood enum_ext.color.red
>>> identity(color(2)) >>> identity(color(2))
enum_ext.color.green enum_ext.color.green
@@ -28,7 +28,7 @@ enum_ext.color.blue
--- check export to scope --- --- check export to scope ---
>>> identity(red) >>> identity(red)
enum_ext.color.blood enum_ext.color.red
>>> identity(green) >>> identity(green)
enum_ext.color.green enum_ext.color.green
@@ -42,18 +42,10 @@ enum_ext.color.blue
>>> c = colorized() >>> c = colorized()
>>> c.x >>> c.x
enum_ext.color.blood enum_ext.color.red
>>> c.x = green >>> c.x = green
>>> c.x >>> c.x
enum_ext.color.green enum_ext.color.green
>>> red == blood
True
>>> red == green
False
>>> hash(red) == hash(blood)
True
>>> hash(red) == hash(green)
False
''' '''
# pickling of enums only works with Python 2.3 or higher # pickling of enums only works with Python 2.3 or higher

View File

@@ -59,13 +59,7 @@ void eval_test()
void exec_test() void exec_test()
{ {
// Register the module with the interpreter // Register the module with the interpreter
if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"), if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"), initembedded_hello) == -1)
#if PY_VERSION_HEX >= 0x03000000
PyInit_embedded_hello
#else
initembedded_hello
#endif
) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's " throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules"); "builtin modules");
// Retrieve the main module // Retrieve the main module
@@ -111,76 +105,49 @@ void exec_test_error()
{ {
// Execute a statement that raises a python exception. // Execute a statement that raises a python exception.
python::dict global; python::dict global;
python::object result = python::exec("print(unknown) \n", global, global); python::object result = python::exec("print unknown \n", global, global);
}
void exercise_embedding_html()
{
using namespace boost::python;
/* code from: libs/python/doc/tutorial/doc/tutorial.qbk
(generates libs/python/doc/tutorial/doc/html/python/embedding.html)
*/
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
object ignored = exec("hello = file('hello.txt', 'w')\n"
"hello.write('Hello world!')\n"
"hello.close()",
main_namespace);
}
void check_pyerr(bool pyerr_expected=false)
{
if (PyErr_Occurred())
{
if (!pyerr_expected) {
BOOST_ERROR("Python Error detected");
PyErr_Print();
}
else {
PyErr_Clear();
}
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
BOOST_TEST(argc == 2 || argc == 3); BOOST_TEST(argc == 2);
std::string script = argv[1]; std::string script = argv[1];
// Initialize the interpreter // Initialize the interpreter
Py_Initialize(); Py_Initialize();
if (python::handle_exception(eval_test)) { if (python::handle_exception(eval_test) ||
check_pyerr(); python::handle_exception(exec_test) ||
} python::handle_exception(boost::bind(exec_file_test, script)))
else if(python::handle_exception(exec_test)) { {
check_pyerr(); if (PyErr_Occurred())
} {
else if (python::handle_exception(boost::bind(exec_file_test, script))) { BOOST_ERROR("Python Error detected");
check_pyerr(); PyErr_Print();
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
} }
if (python::handle_exception(exec_test_error)) if (python::handle_exception(exec_test_error))
{ {
check_pyerr(/*pyerr_expected*/ true); if (PyErr_Occurred())
{
PyErr_Print();
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
} }
else else
{ {
BOOST_ERROR("Python exception expected, but not seen."); BOOST_ERROR("Python exception expected, but not seen.");
} }
if (argc > 2) {
// The main purpose is to test compilation. Since this test generates
// a file and I (rwgk) am uncertain about the side-effects, run it only
// if explicitly requested.
exercise_embedding_html();
}
// Boost.Python doesn't support Py_Finalize yet. // Boost.Python doesn't support Py_Finalize yet.
// Py_Finalize(); // Py_Finalize();
return boost::report_errors(); return boost::report_errors();

View File

@@ -2,5 +2,5 @@
# Software License, Version 1.0. (See accompanying # Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
if 1: print 'Hello World !'
number = 42 number = 42

View File

@@ -53,7 +53,7 @@
>>> ll.push_back(x) >>> ll.push_back(x)
>>> x.push_back(7) >>> x.push_back(7)
>>> ll.push_back(x) >>> ll.push_back(x)
>>> for a in ll: #doctest: +NORMALIZE_WHITESPACE >>> for a in ll:
... for b in a: ... for b in a:
... print b, ... print b,
... print ... print

View File

@@ -7,8 +7,6 @@
#include <boost/python/def.hpp> #include <boost/python/def.hpp>
#include <boost/python/class.hpp> #include <boost/python/class.hpp>
#include <boost/python/list.hpp> #include <boost/python/list.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/make_function.hpp> #include <boost/python/make_function.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#define BOOST_ENABLE_ASSERT_HANDLER #define BOOST_ENABLE_ASSERT_HANDLER
@@ -111,16 +109,11 @@ void exercise(list x, object y, object print)
print("sorted:"); print("sorted:");
x.pop(2); // make sorting predictable x.pop(2); // make sorting predictable
x.pop(2); // remove [1,2] so the list is sortable in py3k
x.sort(); x.sort();
print(x); print(x);
print("reverse sorted:"); print("reverse sorted:");
#if PY_VERSION_HEX >= 0x03000000
x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));
#else
x.sort(&notcmp); x.sort(&notcmp);
#endif
print(x); print(x);
list w; list w;

View File

@@ -73,7 +73,7 @@ X(22)
... ...
>>> y = X(42) >>> y = X(42)
>>> exercise(letters, y, printer) #doctest: +NORMALIZE_WHITESPACE >>> exercise(letters, y, printer)
after append: after append:
['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3)] ['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3)]
number of X(42) instances: 1 number of X(42) instances: 1
@@ -97,9 +97,9 @@ removing 666
reversing... reversing...
['y', 'x', X(3), [1, 2], '.', 'o', 'l', 'l', 'e', 'h'] ['y', 'x', X(3), [1, 2], '.', 'o', 'l', 'l', 'e', 'h']
sorted: sorted:
['.', 'e', 'h', 'l', 'l', 'o', 'x', 'y'] [[1, 2], '.', 'e', 'h', 'l', 'l', 'o', 'x', 'y']
reverse sorted: reverse sorted:
['y', 'x', 'o', 'l', 'l', 'h', 'e', '.'] ['y', 'x', 'o', 'l', 'l', 'h', 'e', '.', [1, 2]]
''' '''
def run(args = None): def run(args = None):

View File

@@ -3,12 +3,12 @@
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
''' '''
>>> from long_ext import * >>> from long_ext import *
>>> print new_long() >>> new_long()
0 0L
>>> print longify(42) >>> longify(42)
42 42L
>>> print longify_string('300') >>> longify_string('300')
300 300L
>>> is_long(20L) >>> is_long(20L)
'yes' 'yes'
>>> is_long('20') >>> is_long('20')

View File

@@ -32,7 +32,8 @@ struct NoddyObject : PyObject
}; };
PyTypeObject NoddyType = { PyTypeObject NoddyType = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(NULL)
0,
const_cast<char*>("Noddy"), const_cast<char*>("Noddy"),
sizeof(NoddyObject), sizeof(NoddyObject),
0, 0,
@@ -103,7 +104,8 @@ struct extract_simple_object
}; };
PyTypeObject SimpleType = { PyTypeObject SimpleType = {
PyVarObject_HEAD_INIT(NULL, 0) PyObject_HEAD_INIT(NULL)
0,
const_cast<char*>("Simple"), const_cast<char*>("Simple"),
sizeof(SimpleObject), sizeof(SimpleObject),
0, 0,

View File

@@ -13,11 +13,6 @@
#include <boost/python/return_value_policy.hpp> #include <boost/python/return_value_policy.hpp>
#include "simple_type.hpp" #include "simple_type.hpp"
#if PY_VERSION_HEX >= 0x03000000
# define PyString_FromString PyUnicode_FromString
# define PyInt_FromLong PyLong_FromLong
#endif
// Get a simple (by value) from the argument, and return the // Get a simple (by value) from the argument, and return the
// string it holds. // string it holds.
PyObject* unwrap_simple(simple x) PyObject* unwrap_simple(simple x)
@@ -57,11 +52,6 @@ PyObject* unwrap_int_const_ref(int const& x)
return PyInt_FromLong(x); return PyInt_FromLong(x);
} }
#if PY_VERSION_HEX >= 0x03000000
# undef PyString_FromString
# undef PyInt_FromLong
#endif
// rewrap<T> extracts a T from the argument, then converts the T back // rewrap<T> extracts a T from the argument, then converts the T back
// to a PyObject* and returns it. // to a PyObject* and returns it.
template <class T> template <class T>

View File

@@ -62,7 +62,7 @@ BOOST_PYTHON_MODULE(map_indexing_suite_ext)
void a_map_indexing_suite(); // moved to a_map_indexing_suite.cpp to void a_map_indexing_suite(); // moved to a_map_indexing_suite.cpp to
a_map_indexing_suite(); // avoid MSVC 6/7 internal structure overflow a_map_indexing_suite(); // avoid MSVC 6/7 internal structure overflow
} }
#include "module_tail.cpp" #include "module_tail.cpp"

View File

@@ -197,7 +197,7 @@ kiwi
>>> tm["kimpo"] = X("bbb") >>> tm["kimpo"] = X("bbb")
>>> print_xmap(tm) >>> print_xmap(tm)
[ (joel, aaa) (kimpo, bbb) ] [ (joel, aaa) (kimpo, bbb) ]
>>> for el in tm: #doctest: +NORMALIZE_WHITESPACE >>> for el in tm:
... print el.key(), ... print el.key(),
... dom = el.data() ... dom = el.data()
joel kimpo joel kimpo

View File

@@ -13,7 +13,6 @@
# endif # endif
# ifdef _MSC_VER # ifdef _MSC_VER
# include <eh.h> // for _set_se_translator()
# pragma warning(push) # pragma warning(push)
# pragma warning(disable:4297) # pragma warning(disable:4297)
# pragma warning(disable:4535) # pragma warning(disable:4535)

View File

@@ -187,11 +187,6 @@ bool check_string_slice()
return s.slice(2,-1).slice(1,-1) == "lo, wor"; return s.slice(2,-1).slice(1,-1) == "lo, wor";
} }
object test_call(object c, object args, object kwds)
{
return c(*args, **kwds);
}
bool check_binary_operators() bool check_binary_operators()
{ {
int y; int y;
@@ -382,7 +377,6 @@ BOOST_PYTHON_MODULE(object_ext)
def("test_item", test_item); def("test_item", test_item);
def("test_not_item", test_not_item); def("test_not_item", test_not_item);
def("test_call", test_call);
def("check_binary_operators", check_binary_operators); def("check_binary_operators", check_binary_operators);
def("check_inplace", check_inplace); def("check_inplace", check_inplace);
def("check_string_slice", check_string_slice); def("check_string_slice", check_string_slice);

View File

@@ -134,12 +134,7 @@
Operators Operators
>>> def print_args(*args, **kwds):
... print args, kwds
>>> test_call(print_args, (0, 1, 2, 3), {'a':'A'})
(0, 1, 2, 3) {'a': 'A'}
>>> assert check_binary_operators() >>> assert check_binary_operators()
>>> class X: pass >>> class X: pass

View File

@@ -1,4 +1,4 @@
# -*- coding: latin-1 -*- # -*- coding: iso-latin-1 -*-
# Copyright Gottfried Ganßauge 2003..2006. Distributed under the Boost # Copyright Gottfried Ganßauge 2003..2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying # Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -40,7 +40,8 @@ namespace boost_python_test {
boost::python::tuple boost::python::tuple
getinitargs(const world& w) getinitargs(const world& w)
{ {
return boost::python::make_tuple(w.get_country()); using namespace boost::python;
return make_tuple(w.get_country());
} }
}; };

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