2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

Python now correctly syntax colorized + some minor tweaks

[SVN r28581]
This commit is contained in:
Joel de Guzman
2005-05-02 15:51:26 +00:00
parent fe3906a7cb
commit a05a0ae46b
12 changed files with 672 additions and 450 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@
<table cellpadding="2" width="100%">
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
<td align="center"><a href="../../../../../../libraries.htm">Libraries</a></td>
<td align="center"><a href="../libraries.html">Libraries</a></td>
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
@@ -26,7 +26,7 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
<a name="hello.from_start_to_finish"></a><h2>
<a name="id446728"></a>From Start To Finish</h2>
<a name="id378425"></a>From Start To Finish</h2>
<p>
Now the first thing you'd want to do is to build the Hello World module and
try it for yourself in Python. In this section, we shall outline the steps
@@ -34,14 +34,12 @@ necessary to achieve that. We shall use the build tool that comes bundled
with every boost distribution: <span class="bold"><b>bjam</b></span>.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td>
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><p></p>
<p></p>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><br><br>
Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as "the one and only way".
There are of course other build tools apart from <tt class="literal">bjam</tt>.<p></p>
<p></p>
There are of course other build tools apart from <tt class="literal">bjam</tt>.<br><br>
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
@@ -95,11 +93,11 @@ the command line. Pre-built Boost.Jam executables are available for most
platforms. The complete list of Bjam executables can be found
<a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.</p>
<a name="hello.let_s_jam_"></a><h2>
<a name="id377058"></a>Let's Jam!</h2>
<p><span class="inlinemediaobject"><img src="../../images/jam.png"></span></p>
<a name="id377025"></a>Let's Jam!</h2>
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
<p>
Here is our minimalist Jamfile:</p>
<pre class="programlisting"><tt class="literal"> subproject libs/python/example/tutorial ;
<pre class="programlisting"><tt class="literal">subproject libs/python/example/tutorial ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
@@ -113,22 +111,22 @@ Here is our minimalist Jamfile:</p>
First, we need to specify our location in the boost project hierarchy.
It so happens that the tutorial example is located in <tt class="literal">/libs/python/example/tutorial</tt>.
Thus:</p>
<pre class="programlisting"><tt class="literal"> subproject libs/python/example/tutorial ;
<pre class="programlisting"><tt class="literal">subproject libs/python/example/tutorial ;
</tt></pre>
<p>
Then we will include the definitions needed by Python modules:</p>
<pre class="programlisting"><tt class="literal"> SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
<pre class="programlisting"><tt class="literal">SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
</tt></pre>
<p>
Finally we declare our <tt class="literal">hello</tt> extension:</p>
<pre class="programlisting"><tt class="literal"> extension hello # Declare a Python extension called hello
<pre class="programlisting"><tt class="literal">extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</tt></pre>
<a name="hello.running_bjam"></a><h2>
<a name="id377153"></a>Running bjam</h2>
<a name="id377119"></a>Running bjam</h2>
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line interpreter.</p>
<div class="blockquote"><blockquote class="blockquote"><p>Start it up.</p></blockquote></div>
<p>
@@ -147,7 +145,7 @@ and that we are using Python version 2.2. You'll have to tweak this path
appropriately.</p>
<div class="informaltable"><table class="table">
<colgroup><col></colgroup>
<tbody><tr><td>
<tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/tip.png"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1",
even if that's the version you have.</td></tr></tbody>
</table></div>
@@ -164,7 +162,7 @@ not, then you will have to specify the appropriate tool. See
further details.</p>
<p>
It should be building now:</p>
<pre class="programlisting"><tt class="literal"> cd C:\dev\boost\libs\python\example\tutorial
<pre class="programlisting"><tt class="literal">cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
@@ -172,7 +170,7 @@ It should be building now:</p>
</tt></pre>
<p>
And so on... Finally:</p>
<pre class="programlisting"><tt class="literal"> vc-C++ ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
<pre class="programlisting"><tt class="literal">vc-C++ ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.obj
hello.cpp
vc-Link ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
@@ -213,14 +211,16 @@ can simply put these libraries inside the directory where the Python
executable is.</p>
<p>
You may now fire up Python and run our hello module:</p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="identifier"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
<p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier">
hello</span><span class="special">,</span><span class="identifier"> world</span></tt></pre>
<p></p>
<div class="blockquote"><blockquote class="blockquote"><p><span class="bold"><b>There you go... Have fun!</b></span></p></blockquote></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><small>Copyright © 2002-2004 Joel de Guzman, David Abrahams</small></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td>
</tr></table>
<hr>
<div class="spirit-nav">

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
[library python
[version 1.0]
[authors [de Guzman, Joel], [Abrahams, David]]
[copyright 2002 2003 2004 Joel de Guzman, David Abrahams]
[copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams]
[category inter-language support]
[purpose
Reflects C++ classes and functions into Python
@@ -21,6 +21,7 @@
[def __alert__ [$images/alert.png]]
[def __tip__ [$images/tip.png]]
[def :-) [$images/smiley.png]]
[def __jam__ [$images/jam.png]]
[section QuickStart]
@@ -58,10 +59,14 @@ can be exposed to Python by writing a Boost.Python wrapper:
That's it. We're done. We can now build this as a shared library. The
resulting DLL is now visible to Python. Here's a sample Python session:
[python]
>>> import hello
>>> print hello.greet()
hello, world
[c++]
[:['[*Next stop... Building your Hello World module from start to finish...]]]
[endsect]
@@ -115,7 +120,7 @@ platforms. The complete list of Bjam executables can be found
[@http://sourceforge.net/project/showfiles.php?group_id=7586 here].
[h2 Let's Jam!]
[$../images/jam.png]
__jam__
Here is our minimalist Jamfile:
@@ -238,10 +243,14 @@ executable is.
You may now fire up Python and run our hello module:
[python]
>>> import hello
>>> print hello.greet()
hello, world
[c++]
[:[*There you go... Have fun!]]
[endsect]
@@ -276,6 +285,8 @@ Here, we wrote a C++ class wrapper that exposes the member functions
[^greet] and [^set]. Now, after building our module as a shared library, we
may use our class [^World] in Python. Here's a sample Python session:
[python]
>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
@@ -294,6 +305,8 @@ which is why we were able to write
We may wish to wrap a class with a non-default constructor. Let us
build on our previous example:
[c++]
struct World
{
World(std::string msg): msg(msg) {} // added constructor
@@ -364,6 +377,8 @@ Our C++ [^Var] class and its data members can be exposed to Python:
Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:
[python]
>>> x = hello.Var('pi')
>>> x.value = 3.14
>>> print x.name, 'is around', x.value
@@ -372,12 +387,10 @@ hello as we did before:
Note that [^name] is exposed as [*read-only] while [^value] is exposed
as [*read-write].
[pre
>>> x.name = 'e' # can't change name
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
]
[endsect]
[section Class Properties]
@@ -388,6 +401,8 @@ the class' data members. The only way to access the class' data is
through access (getter/setter) functions. Access functions expose class
properties. Here's an example:
[c++]
struct Num
{
Num();
@@ -407,6 +422,8 @@ attributes can just be a different syntax for a method call. Wrapping our
And at last, in Python:
[python]
>>> x = Num()
>>> x.value = 3.14
>>> x.value, x.rovalue
@@ -416,6 +433,8 @@ And at last, in Python:
Take note that the class property [^rovalue] is exposed as [*read-only]
since the [^rovalue] setter member function is not passed in:
[c++]
.add_property("rovalue", &Num::get)
[endsect]
@@ -513,7 +532,7 @@ inherited `wrapper<Base>` (See [@../../../v2/wrapper.html Wrapper]). The
`wrapper` template makes the job of wrapping classes that are meant to
overridden in Python, easier.
[blurb __alert__ MSVC6/7 Workaround\n\n
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:\n\n
`return call<int>(this->get_override("f").ptr());`.]
@@ -577,7 +596,7 @@ We wrap it this way:
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
override for `f`. If none, then we call `Base::f()`.
[blurb __alert__ MSVC6/7 Workaround\n\n
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
with the `*note*` as:\n\n
`return call<char const*>(f.ptr());`.]
@@ -595,6 +614,8 @@ special [^def] function for this purpose.
In Python, the results would be as expected:
[python]
>>> base = Base()
>>> class Derived(Base):
... def f(self):
@@ -624,6 +645,8 @@ this and makes it easy to wrap C++ operator-powered classes.
Consider a file position class [^FilePos] and a set of operators that take
on FilePos instances:
[c++]
class FilePos { /*...*/ };
FilePos operator+(FilePos, int);
@@ -676,9 +699,9 @@ that correspond to these Python ['special functions]. Example:
Need we say more?
[blurb __note__ What is the business of [^operator<<] [^.def(str(self))]?
Well, the method [^str] requires the [^operator<<] to do its work (i.e.
[^operator<<] is used by the method defined by def(str(self)).]
[blurb __note__ What is the business of `operator<<`?
Well, the method `str` requires the `operator<<` to do its work (i.e.
`operator<<` is used by the method defined by `def(str(self))`.]
[endsect]
[endsect] [/ Exposing Classes ]
@@ -771,6 +794,8 @@ Here's what's happening:
We could copy result into a new object:
[python]
>>> f(y, z).set(42) # Result disappears
>>> y.x.get() # No crash, but still bad
3.14
@@ -781,6 +806,8 @@ closely as possible.
Our problems do not end there. Suppose Y is implemented as follows:
[c++]
struct Y
{
X x; Z* z;
@@ -1117,6 +1144,8 @@ Class [^object] wraps [^PyObject*]. All the intricacies of dealing with
To illustrate, this Python code snippet:
[python]
def f(x, y):
if (y == 'foo'):
x[3:7] = 'bar'
@@ -1129,6 +1158,8 @@ To illustrate, this Python code snippet:
Can be rewritten in C++ using Boost.Python facilities this way:
[c++]
object f(object x, object y) {
if (y == "foo")
x.slice(3,7) = "bar";
@@ -1194,18 +1225,22 @@ member functions.
Demonstrates that you can write the C++ equivalent of [^"format" % x,y,z]
in Python, which is useful since there's no easy way to do that in std C++.
__alert__ [*Beware] the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.
[blurb
__alert__ [*Beware] the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.
]
Python:
[python]
>>> d = dict(x.__dict__) # copies x.__dict__
>>> d['whatever'] # modifies the copy
C++:
[c++]
dict d(x.attr("__dict__")); # copies x.__dict__
d['whatever'] = 3; # modifies the copy
dict d(x.attr("__dict__")); // copies x.__dict__
d['whatever'] = 3; // modifies the copy
[h2 class_<T> as objects]
@@ -1292,12 +1327,16 @@ attributes. Details can be found [@../../../v2/scope.html here].]
You can access those values in Python as
[python]
>>> my_module.choice.red
my_module.choice.red
where my_module is the module where the enum is declared. You can also
create a new scope around a class:
[c++]
scope in_X = class_<X>("X")
.def( ... )
.def( ... )
@@ -1497,10 +1536,12 @@ the object's [^ptr] member function to retrieve the [^PyObject*].
This should create a file called 'hello.txt' in the current directory
containing a phrase that is well-known in programming circles.
__note__ [*Note] that we wrap the return value of PyRun_String in a
(nameless) [^handle] even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
[blurb
__note__ [*Note] that we wrap the return value of PyRun_String in a
(nameless) [^handle] even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
]
[h2 Beyond handles]
@@ -1542,10 +1583,12 @@ PyRun_String return the result directly with Py_eval_input:
int five_squared = extract<int>(result);
__note__ [*Note] that [^object]'s member function to return the wrapped
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
take into account the different functions that [^object] and [^handle]
perform.
[blurb
__note__ [*Note] that [^object]'s member function to return the wrapped
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
take into account the different functions that [^object] and [^handle]
perform.
]
[h2 Exception handling]
@@ -1634,6 +1677,8 @@ iterators, but these are two very different beasts.
The typical Python iteration protocol: [^[*for y in x...]] is as follows:
[python]
iter = x.__iter__() # get iterator
try:
while 1:
@@ -1646,6 +1691,8 @@ nicely as Python iterators. What we need to do is to produce
appropriate __iter__ function from C++ iterators that is compatible
with the Python iteration protocol. For example:
[c++]
object get_iterator = iterator<vector<int> >();
object iter = get_iterator(v);
object first = iter.next();
@@ -1677,6 +1724,8 @@ with &T::begin, &T::end.
Let's put this into action... Here's an example from some hypothetical
bogon Particle accelerator code:
[python]
f = Field()
for x in f.pions:
smash(x)
@@ -1685,6 +1734,8 @@ bogon Particle accelerator code:
Now, our C++ Wrapper:
[c++]
class_<F>("Field")
.property("pions", range(&F::p_begin, &F::p_end))
.property("bogons", range(&F::b_begin, &F::b_end));
@@ -1789,6 +1840,8 @@ Now our package is ready. All the user has to do is put [^sounds] into his
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH]
and fire up the interpreter:
[python]
>>> import sounds.io
>>> import sounds.filters
>>> sound = sounds.io.open('file.mp3')
@@ -1806,6 +1859,8 @@ it.
If we want this flexibility, we will have to complicate our package hierarchy a
little. First, we will have to change the name of the extension modules:
[c++]
/* file core.cpp */
BOOST_PYTHON_MODULE(_core)
{
@@ -1835,6 +1890,8 @@ Note that we created a directory for each extension module, and added a
__init__.py to each one. But if we leave it that way, the user will have to
access the functions in the core module with this syntax:
[python]
>>> import sounds.core._core
>>> sounds.core._core.foo(...)
@@ -1899,6 +1956,8 @@ Yes, Python rox. :-)
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class [^point] in C++:
[c++]
class point {...};
BOOST_PYTHON_MODULE(_geom)
@@ -1910,6 +1969,8 @@ If we are using the technique from the previous session,
[link python.creating_packages Creating Packages], we can code directly
into [^geom/__init__.py]:
[python]
from _geom import *
# a regular function
@@ -1977,6 +2038,8 @@ time to compile the Boost.Python wrappers. Plus the memory consumption can
easily become too high. If this is causing you problems, you can split the
class_ definitions in multiple files:
[c++]
/* file point.cpp */
#include <point.h>
#include <boost/python.hpp>