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:
@@ -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=../../../../../..
|
||||
;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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">>>></span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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>
|
||||
|
||||
@@ -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>
|
||||
<find-library>$(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"><boost/python.hpp></tt><p></p>
|
||||
<p></p>
|
||||
#include <tt class="literal"><boost/python.hpp></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<></tt> instead of the longer, but equivalent, <tt class="literal">handle<PyObject></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<></tt> instead of the longer, but equivalent, <tt class="literal">handle<PyObject></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"><</span><span class="keyword">int</span><span class="special">>(</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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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">
|
||||
>>></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">
|
||||
>>></span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="char">
|
||||
>>></span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span><span class="special">
|
||||
>>></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">>>></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">>>></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">
|
||||
>>></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">
|
||||
>>></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>
|
||||
>>></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"> >>> x.name = 'e' # can't change name
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: can't set attribute
|
||||
</tt></pre>
|
||||
<pre class="programlisting"><tt class="literal"><span class="special">>>></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"> "<stdin>"</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"> &</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span><span class="special"> &</span><span class="identifier">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">>>></span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> Num</span><span class="special">()</span><span class="special">
|
||||
>>></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">
|
||||
>>></span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special">
|
||||
(</span><span class="number">3.14</span><span class="special">,</span><span class="number"> 3.14</span><span class="special">)</span><span class="special">
|
||||
>>></span><span class="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>
|
||||
>>></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"> &</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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt> in effect calls the
|
||||
@@ -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"><</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
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"><</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
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">>>></span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="special">
|
||||
>>></span><span class="keyword"> class</span><span class="identifier"> Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span><span class="special">
|
||||
...</span><span class="identifier"> def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="special">
|
||||
...</span><span class="keyword"> 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">
|
||||
>>></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<T>()</tt> in place of an actual
|
||||
<tt class="literal">T</tt> instance when writing "self expressions".</p>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||
<a name="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">&</span><span class="keyword"> operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier">
|
||||
|
||||
class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>()</span><span class="special">
|
||||
class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</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"><</span><span class="identifier">Rational</span><span class="special">>))</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"><</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<<</tt><tt class="literal">.def(str(self))</tt>?
|
||||
Well, the method <tt class="literal">str</tt> requires the <tt class="literal">operator<<</tt> to do its work (i.e.
|
||||
<tt class="literal">operator<<</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"><<</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"><<</span></tt> to do its work (i.e.
|
||||
<tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</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">
|
||||
|
||||
@@ -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">>>> import this</tt>.</p>
|
||||
<pre class="programlisting"><tt class="literal"> >>> import this
|
||||
<pre class="programlisting"><tt class="literal">>>> 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">>>></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">
|
||||
>>></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">>>></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">>>></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<T> with T one of:</b></span><p></p>
|
||||
<span class="bold"><b>return_value_policy<T> 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<...></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">
|
||||
|
||||
@@ -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
|
||||
<dll>../../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">>>></span><span class="identifier"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
||||
>>></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">
|
||||
|
||||
@@ -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"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special"> >();</span><span class="identifier">
|
||||
object</span><span class="identifier"> iter</span><span class="special"> =</span><span class="identifier"> get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span><span class="identifier">
|
||||
object</span><span class="identifier"> first</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span></tt></pre>
|
||||
@@ -105,20 +108,22 @@ with &T::begin, &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"><</span><span class="identifier">F</span><span class="special">>(</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span><span class="special"> &</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span><span class="special"> &</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">
|
||||
|
||||
@@ -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">>>></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">
|
||||
>>></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">>>></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">>>></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_<T> as objects</h2>
|
||||
<a name="id459197"></a>class_<T> as objects</h2>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt> may
|
||||
also be one of these types! The following code snippet wraps the class
|
||||
@@ -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">>>></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"><</span><span class="identifier">X</span><span class="special">>(</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">
|
||||
|
||||
@@ -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">>>></span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
|
||||
>>></span><span class="identifier"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
||||
>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">
|
||||
>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
||||
>>></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">
|
||||
>>></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">>>></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">>>></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">
|
||||
>>></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">>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</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></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">>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</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_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">>>></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">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></span> #<span class="identifier"> a</span><span class="identifier"> regular</span><span class="identifier"> function</span><span class="special">
|
||||
>>></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">
|
||||
>>></span><span class="comment"> # a regular function
|
||||
</span><span class="special">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></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">
|
||||
>>></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">
|
||||
>>></span><span class="comment"> # now we turn it in a member function
|
||||
</span><span class="special">>>></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">
|
||||
>>></span><span class="special">
|
||||
>>></span><span class="identifier"> c</span><span class="special"> =</span><span class="identifier"> C</span><span class="special">()</span><span class="special">
|
||||
>>></span><span class="identifier"> print</span><span class="identifier"> c</span><span class="identifier">
|
||||
>>></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">
|
||||
>>></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">>>></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">>>></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">
|
||||
>>></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"> <</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
||||
#include</span><span class="special"> <</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">></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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user