2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00
Files
python/doc/tutorial/doc/tutorial.xml
Aleksey Gurtovoy b77dcf4bea merge RC_1_32_0 fixes
[SVN r26330]
2004-11-28 03:54:58 +00:00

2571 lines
196 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library
id="python"
name="python"
dirname="python"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
<author>
<firstname>Joel</firstname>
<surname>de Guzman</surname>
</author>
<author>
<firstname>David</firstname>
<surname>Abrahams</surname>
</author>
<copyright>
<year>2002</year>
<year>2003</year>
<year>2004</year>
<holder>Joel de Guzman, David Abrahams</holder>
</copyright>
<legalnotice>
<para>
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
<ulink url="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt
</ulink>)
</para>
</legalnotice>
<librarypurpose>
Reflects C++ classes and functions into Python
</librarypurpose>
<librarycategory name="category:inter-language support"></librarycategory>
</libraryinfo>
<title>python 1.0</title>
<section id="python.quickstart">
<title>QuickStart</title>
<para>
The Boost Python Library is a framework for interfacing Python and
C++. It allows you to quickly and seamlessly expose C++ classes
functions and objects to Python, and vice-versa, using no special
tools -- just your C++ compiler. It is designed to wrap C++ interfaces
non-intrusively, so that you should not have to change the C++ code at
all in order to wrap it, making Boost.Python ideal for exposing
3rd-party libraries to Python. The library's use of advanced
metaprogramming techniques simplifies its syntax for users, so that
wrapping code takes on the look of a kind of declarative interface
definition language (IDL).</para>
<anchor id="quickstart.hello_world" /><bridgehead renderas="sect2">Hello World</bridgehead><para>
Following C/C++ tradition, let's start with the &quot;hello, world&quot;. A C++
Function:</para>
<programlisting>
<literal>
<phrase role="keyword">char</phrase><phrase role="keyword"> const</phrase><phrase role="special">*</phrase><phrase role="identifier"> greet</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="string"> &quot;hello, world&quot;</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
can be exposed to Python by writing a Boost.Python wrapper:</para>
<programlisting>
<literal>
<phrase role="preprocessor">#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="keyword">
using</phrase><phrase role="keyword"> namespace</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">python</phrase><phrase role="special">;</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">hello</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;greet&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> greet</phrase><phrase role="special">);</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
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:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> hello</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> print</phrase><phrase role="identifier"> hello</phrase><phrase role="special">.</phrase><phrase role="identifier">greet</phrase><phrase role="special">()</phrase><phrase role="identifier">
hello</phrase><phrase role="special">,</phrase><phrase role="identifier"> world</phrase>
</literal>
</programlisting>
<blockquote><para><emphasis><emphasis role="bold">Next stop... Building your Hello World module from start to finish...</emphasis></emphasis></para></blockquote></section>
<section id="python.hello">
<title> Building Hello World</title>
<anchor id="hello.from_start_to_finish" /><bridgehead renderas="sect2">From Start To Finish</bridgehead><para>
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
necessary to achieve that. We shall use the build tool that comes bundled
with every boost distribution: <emphasis role="bold">bjam</emphasis>.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Building without bjam</emphasis><para/>
<para/>
Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as &quot;the one and only way&quot;.
There are of course other build tools apart from <literal>bjam</literal>.<para/>
<para/>
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
that 90% of the &quot;I can't build Boost.Python&quot; problems come from people
who had to use a different tool.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
We shall skip over the details. Our objective will be to simply create the
hello world module and run it in Python. For a complete reference to
building Boost.Python, check out: <ulink url="../../../building.html">building.html</ulink>.
After this brief <emphasis>bjam</emphasis> tutorial, we should have built two DLLs:</para>
<itemizedlist>
<listitem>
boost_python.dll
</listitem><listitem>
hello.pyd
</listitem>
</itemizedlist><para>
if you are on Windows, and</para>
<itemizedlist>
<listitem>
libboost_python.so
</listitem><listitem>
hello.so
</listitem>
</itemizedlist><para>
if you are on Unix.</para>
<para>
The tutorial example can be found in the directory:
<literal>libs/python/example/tutorial</literal>. There, you can find:</para>
<itemizedlist>
<listitem>
hello.cpp
</listitem><listitem>
Jamfile
</listitem>
</itemizedlist><para>
The <literal>hello.cpp</literal> file is our C++ hello world example. The <literal>Jamfile</literal> is a
minimalist <emphasis>bjam</emphasis> script that builds the DLLs for us.</para>
<para>
Before anything else, you should have the bjam executable in your boost
directory or somewhere in your path such that <literal>bjam</literal> can be executed in
the command line. Pre-built Boost.Jam executables are available for most
platforms. The complete list of Bjam executables can be found
<ulink url="http://sourceforge.net/project/showfiles.php?group_id=7586">here</ulink>.</para>
<anchor id="hello.let_s_jam_" /><bridgehead renderas="sect2">Let's Jam!</bridgehead><para>
<inlinemediaobject><imageobject><imagedata fileref="../images/jam.png"></imagedata></imageobject></inlinemediaobject></para>
<para>
Here is our minimalist Jamfile:</para>
<programlisting><literal> subproject libs/python/example/tutorial ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</literal></programlisting><para>
First, we need to specify our location in the boost project hierarchy.
It so happens that the tutorial example is located in <literal>/libs/python/example/tutorial</literal>.
Thus:</para>
<programlisting><literal> subproject libs/python/example/tutorial ;
</literal></programlisting><para>
Then we will include the definitions needed by Python modules:</para>
<programlisting><literal> SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
</literal></programlisting><para>
Finally we declare our <literal>hello</literal> extension:</para>
<programlisting><literal> extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</literal></programlisting><anchor id="hello.running_bjam" /><bridgehead renderas="sect2">Running bjam</bridgehead><para>
<emphasis>bjam</emphasis> is run using your operating system's command line interpreter.</para>
<blockquote><para>Start it up.</para></blockquote><para>
Make sure that the environment is set so that we can invoke the C++
compiler. With MSVC, that would mean running the <literal>Vcvars32.bat</literal> batch
file. For instance:</para>
<programlisting>
<literal>
<phrase role="identifier">C</phrase><phrase role="special">:\</phrase><phrase role="identifier">Program</phrase><phrase role="identifier"> Files</phrase><phrase role="special">\</phrase><phrase role="identifier">Microsoft</phrase><phrase role="identifier"> Visual</phrase><phrase role="identifier"> Studio</phrase><phrase role="special">\</phrase><phrase role="identifier">VC98</phrase><phrase role="special">\</phrase><phrase role="identifier">bin</phrase><phrase role="special">\</phrase><phrase role="identifier">Vcvars32</phrase><phrase role="special">.</phrase><phrase role="identifier">bat</phrase>
</literal>
</programlisting>
<para>
Some environment variables will have to be setup for proper building of our
Python modules. Example:</para>
<programlisting>
<literal>
<phrase role="identifier">set</phrase><phrase role="identifier"> PYTHON_ROOT</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">:/</phrase><phrase role="identifier">dev</phrase><phrase role="special">/</phrase><phrase role="identifier">tools</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="identifier">
set</phrase><phrase role="identifier"> PYTHON_VERSION</phrase><phrase role="special">=</phrase><phrase role="number">2.2</phrase>
</literal>
</programlisting>
<para>
The above assumes that the Python installation is in <literal>c:/dev/tools/python</literal>
and that we are using Python version 2.2. You'll have to tweak this path
appropriately.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/tip.png"></imagedata></imageobject></inlinemediaobject> Be sure not to include a third number, e.g. <emphasis role="bold">not</emphasis> &quot;2.2.1&quot;,
even if that's the version you have.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
Now we are ready... Be sure to <literal>cd</literal> to <literal>libs/python/example/tutorial</literal>
where the tutorial <literal>&quot;hello.cpp&quot;</literal> and the <literal>&quot;Jamfile&quot;</literal> is situated.</para>
<para>
Finally:</para>
<programlisting>
<literal>
<phrase role="identifier">bjam</phrase><phrase role="special"> -</phrase><phrase role="identifier">sTOOLS</phrase><phrase role="special">=</phrase><phrase role="identifier">msvc</phrase>
</literal>
</programlisting>
<para>
We are again assuming that we are using Microsoft Visual C++ version 6. If
not, then you will have to specify the appropriate tool. See
<ulink url="../../../../../../tools/build/index.html">Building Boost Libraries</ulink> for
further details.</para>
<para>
It should be building now:</para>
<programlisting><literal> cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
</literal></programlisting><para>
And so on... Finally:</para>
<programlisting><literal> vc-C++ ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.obj
hello.cpp
vc-Link ........\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
runtime-link-dynamic\hello.pyd ........\libs\python\example\tutorial\bin\
hello.pyd\msvc\debug\runtime-link-dynamic\hello.lib
Creating library ........\libs\python\example\tutorial\bin\hello.pyd\
msvc\debug\runtime-link-dynamic\hello.lib and object ........\libs\python\
example\tutorial\bin\hello.pyd\msvc\debug\runtime-link-dynamic\hello.exp
...updated 40 targets...
</literal></programlisting><para>
If all is well, you should now have:</para>
<itemizedlist>
<listitem>
boost_python.dll
</listitem><listitem>
hello.pyd
</listitem>
</itemizedlist><para>
if you are on Windows, and</para>
<itemizedlist>
<listitem>
libboost_python.so
</listitem><listitem>
hello.so
</listitem>
</itemizedlist><para>
if you are on Unix.</para>
<para>
<literal>boost_python.dll</literal> can be found somewhere in <literal>libs\python\build\bin</literal>
while <literal>hello.pyd</literal> can be found somewhere in
<literal>libs\python\example\tutorial\bin</literal>. After a successful build, you can just
link in these DLLs with the Python interpreter. In Windows for example, you
can simply put these libraries inside the directory where the Python
executable is.</para>
<para>
You may now fire up Python and run our hello module:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> hello</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> print</phrase><phrase role="identifier"> hello</phrase><phrase role="special">.</phrase><phrase role="identifier">greet</phrase><phrase role="special">()</phrase><phrase role="identifier">
hello</phrase><phrase role="special">,</phrase><phrase role="identifier"> world</phrase>
</literal>
</programlisting>
<blockquote><para><emphasis role="bold">There you go... Have fun!</emphasis></para></blockquote></section>
<section id="python.exposing">
<title> Exposing Classes</title>
<para>
Now let's expose a C++ class to Python.</para>
<para>
Consider a C++ class/struct that we want to expose to Python:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> World</phrase><phrase role="special">
{</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> set</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> msg</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="keyword"> this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">msg</phrase><phrase role="special"> =</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="identifier">
std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> greet</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="identifier">
std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
We can expose this to Python by writing a corresponding Boost.Python
C++ Wrapper:</para>
<programlisting>
<literal>
<phrase role="preprocessor">#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="keyword">
using</phrase><phrase role="keyword"> namespace</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">python</phrase><phrase role="special">;</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">hello</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">World</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;World&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;greet&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">greet</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;set&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Here, we wrote a C++ class wrapper that exposes the member functions
<literal>greet</literal> and <literal>set</literal>. Now, after building our module as a shared library, we
may use our class <literal>World</literal> in Python. Here's a sample Python session:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> hello</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> planet</phrase><phrase role="special"> =</phrase><phrase role="identifier"> hello</phrase><phrase role="special">.</phrase><phrase role="identifier">World</phrase><phrase role="special">()</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> planet</phrase><phrase role="special">.</phrase><phrase role="identifier">set</phrase><phrase role="special">(</phrase><phrase role="char">'howdy'</phrase><phrase role="special">)</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> planet</phrase><phrase role="special">.</phrase><phrase role="identifier">greet</phrase><phrase role="special">()</phrase><phrase role="char">
'howdy'</phrase>
</literal>
</programlisting>
<section id="python.constructors">
<title>Constructors</title>
<para>
Our previous example didn't have any explicit constructors.
Since <literal>World</literal> is declared as a plain struct, it has an implicit default
constructor. Boost.Python exposes the default constructor by default,
which is why we were able to write</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> planet</phrase><phrase role="special"> =</phrase><phrase role="identifier"> hello</phrase><phrase role="special">.</phrase><phrase role="identifier">World</phrase><phrase role="special">()</phrase>
</literal>
</programlisting>
<para>
We may wish to wrap a class with a non-default constructor. Let us
build on our previous example:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> World</phrase><phrase role="special">
{</phrase><phrase role="identifier">
World</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> msg</phrase><phrase role="special">):</phrase><phrase role="identifier"> msg</phrase><phrase role="special">(</phrase><phrase role="identifier">msg</phrase><phrase role="special">)</phrase><phrase role="special"> {}</phrase><phrase role="comment"> // added constructor
</phrase><phrase role="keyword"> void</phrase><phrase role="identifier"> set</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> msg</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="keyword"> this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">msg</phrase><phrase role="special"> =</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="identifier">
std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> greet</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="identifier">
std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> msg</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
This time <literal>World</literal> has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose
it. We have to tell <literal>class_&lt;World&gt;</literal> about the constructor we want to
expose instead.</para>
<programlisting>
<literal>
<phrase role="preprocessor">#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="keyword">
using</phrase><phrase role="keyword"> namespace</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">python</phrase><phrase role="special">;</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">hello</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">World</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;World&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> init</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;greet&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">greet</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;set&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
<literal>init&lt;std::string&gt;()</literal> exposes the constructor taking in a
<literal>std::string</literal> (in Python, constructors are spelled
&quot;<literal>&quot;<emphasis role="underline">_init</emphasis>_&quot;</literal>&quot;).</para>
<para>
We can expose additional constructors by passing more <literal>init&lt;...&gt;</literal>s to
the <literal>def()</literal> member function. Say for example we have another World
constructor taking in two doubles:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">World</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;World&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> init</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">init</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;greet&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">greet</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;set&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">World</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
On the other hand, if we do not wish to expose any constructors at
all, we may use <literal>no_init</literal> instead:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Abstract</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Abstract&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> no_init</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
This actually adds an <literal><emphasis role="underline">_init</emphasis>_</literal> method which always raises a
Python RuntimeError exception.</para>
</section>
<section id="python.class_data_members">
<title>Class Data Members</title>
<para>
Data members may also be exposed to Python so that they can be
accessed as attributes of the corresponding Python class. Each data
member that we wish to be exposed may be regarded as <emphasis role="bold">read-only</emphasis> or
<emphasis role="bold">read-write</emphasis>. Consider this class <literal>Var</literal>:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Var</phrase><phrase role="special">
{</phrase><phrase role="identifier">
Var</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> name</phrase><phrase role="special">)</phrase><phrase role="special"> :</phrase><phrase role="identifier"> name</phrase><phrase role="special">(</phrase><phrase role="identifier">name</phrase><phrase role="special">),</phrase><phrase role="identifier"> value</phrase><phrase role="special">()</phrase><phrase role="special"> {}</phrase><phrase role="identifier">
std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="keyword"> const</phrase><phrase role="identifier"> name</phrase><phrase role="special">;</phrase><phrase role="keyword">
float</phrase><phrase role="identifier"> value</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
Our C++ <literal>Var</literal> class and its data members can be exposed to Python:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Var</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Var&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> init</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def_readonly</phrase><phrase role="special">(</phrase><phrase role="string">&quot;name&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Var</phrase><phrase role="special">::</phrase><phrase role="identifier">name</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def_readwrite</phrase><phrase role="special">(</phrase><phrase role="string">&quot;value&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Var</phrase><phrase role="special">::</phrase><phrase role="identifier">value</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special"> =</phrase><phrase role="identifier"> hello</phrase><phrase role="special">.</phrase><phrase role="identifier">Var</phrase><phrase role="special">(</phrase><phrase role="char">'pi'</phrase><phrase role="special">)</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">value</phrase><phrase role="special"> =</phrase><phrase role="number"> 3.14</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> print</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">name</phrase><phrase role="special">,</phrase><phrase role="char"> 'is around'</phrase><phrase role="special">,</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">value</phrase><phrase role="identifier">
pi</phrase><phrase role="identifier"> is</phrase><phrase role="identifier"> around</phrase><phrase role="number"> 3.14</phrase>
</literal>
</programlisting>
<para>
Note that <literal>name</literal> is exposed as <emphasis role="bold">read-only</emphasis> while <literal>value</literal> is exposed
as <emphasis role="bold">read-write</emphasis>.</para>
<programlisting><literal> &gt;&gt;&gt; x.name = 'e' # can't change name
Traceback (most recent call last):
File &quot;&lt;stdin&gt;&quot;, line 1, in ?
AttributeError: can't set attribute
</literal></programlisting></section>
<section id="python.class_properties">
<title>Class Properties</title>
<para>
In C++, classes with public data members are usually frowned
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:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Num</phrase><phrase role="special">
{</phrase><phrase role="identifier">
Num</phrase><phrase role="special">();</phrase><phrase role="keyword">
float</phrase><phrase role="identifier"> get</phrase><phrase role="special">()</phrase><phrase role="keyword"> const</phrase><phrase role="special">;</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> set</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="identifier"> value</phrase><phrase role="special">);</phrase><phrase role="special">
...</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
However, in Python attribute access is fine; it doesn't neccessarily break
encapsulation to let users handle attributes directly, because the
attributes can just be a different syntax for a method call. Wrapping our
<literal>Num</literal> class using Boost.Python:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Num</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Num&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">add_property</phrase><phrase role="special">(</phrase><phrase role="string">&quot;rovalue&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Num</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">add_property</phrase><phrase role="special">(</phrase><phrase role="string">&quot;value&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Num</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Num</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
And at last, in Python:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Num</phrase><phrase role="special">()</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">value</phrase><phrase role="special"> =</phrase><phrase role="number"> 3.14</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">value</phrase><phrase role="special">,</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">rovalue</phrase><phrase role="special">
(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase><phrase role="number"> 3.14</phrase><phrase role="special">)</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">rovalue</phrase><phrase role="special"> =</phrase><phrase role="number"> 2.17</phrase>&nbsp;#<phrase role="identifier"> error</phrase><phrase role="special">!</phrase>
</literal>
</programlisting>
<para>
Take note that the class property <literal>rovalue</literal> is exposed as <emphasis role="bold">read-only</emphasis>
since the <literal>rovalue</literal> setter member function is not passed in:</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">add_property</phrase><phrase role="special">(</phrase><phrase role="string">&quot;rovalue&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Num</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
</section>
<section id="python.inheritance">
<title>Inheritance</title>
<para>
In the previous examples, we dealt with classes that are not polymorphic.
This is not often the case. Much of the time, we will be wrapping
polymorphic classes and class hierarchies related by inheritance. We will
often have to write Boost.Python wrappers for classes that are derived from
abstract base classes.</para>
<para>
Consider this trivial inheritance structure:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special"> {</phrase><phrase role="keyword"> virtual</phrase><phrase role="special"> ~</phrase><phrase role="identifier">Base</phrase><phrase role="special">();</phrase><phrase role="special"> };</phrase><phrase role="keyword">
struct</phrase><phrase role="identifier"> Derived</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special"> {};</phrase>
</literal>
</programlisting>
<para>
And a set of C++ functions operating on <literal>Base</literal> and <literal>Derived</literal> object
instances:</para>
<programlisting>
<literal>
<phrase role="keyword">void</phrase><phrase role="identifier"> b</phrase><phrase role="special">(</phrase><phrase role="identifier">Base</phrase><phrase role="special">*);</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> d</phrase><phrase role="special">(</phrase><phrase role="identifier">Derived</phrase><phrase role="special">*);</phrase><phrase role="identifier">
Base</phrase><phrase role="special">*</phrase><phrase role="identifier"> factory</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="keyword"> new</phrase><phrase role="identifier"> Derived</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase>
</literal>
</programlisting>
<para>
We've seen how we can wrap the base class <literal>Base</literal>:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Base&quot;</phrase><phrase role="special">)</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
Now we can inform Boost.Python of the inheritance relationship between
<literal>Derived</literal> and its base class <literal>Base</literal>. Thus:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Derived</phrase><phrase role="special">,</phrase><phrase role="identifier"> bases</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">&gt;</phrase><phrase role="special"> &gt;(</phrase><phrase role="string">&quot;Derived&quot;</phrase><phrase role="special">)</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
Doing so, we get some things for free:</para>
<orderedlist>
<listitem>
Derived automatically inherits all of Base's Python methods
(wrapped C++ member functions)
</listitem><listitem>
<emphasis role="bold">If</emphasis> Base is polymorphic, <literal>Derived</literal> objects which have been passed to
Python via a pointer or reference to <literal>Base</literal> can be passed where a pointer
or reference to <literal>Derived</literal> is expected.
</listitem>
</orderedlist><para>
Now, we shall expose the C++ free functions <literal>b</literal> and <literal>d</literal> and <literal>factory</literal>:</para>
<programlisting>
<literal>
<phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;b&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> b</phrase><phrase role="special">);</phrase><phrase role="identifier">
def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;d&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> d</phrase><phrase role="special">);</phrase><phrase role="identifier">
def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;factory&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> factory</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
Note that free function <literal>factory</literal> is being used to generate new
instances of class <literal>Derived</literal>. In such cases, we use
<literal>return_value_policy&lt;manage_new_object&gt;</literal> to instruct Python to adopt
the pointer to <literal>Base</literal> and hold the instance in a new Python <literal>Base</literal>
object until the the Python object is destroyed. We shall see more of
Boost.Python <link linkend="python.call_policies">call policies</link> later.</para>
<programlisting>
<literal>
<phrase role="comment">// Tell Python to take ownership of factory's result
</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;factory&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> factory</phrase><phrase role="special">,</phrase><phrase role="identifier">
return_value_policy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">manage_new_object</phrase><phrase role="special">&gt;());</phrase>
</literal>
</programlisting>
</section>
<section id="python.class_virtual_functions">
<title>Class Virtual Functions</title>
<para>
In this section, we shall learn how to make functions behave polymorphically
through virtual functions. Continuing our example, let us add a virtual function
to our <literal>Base</literal> class:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
{</phrase><phrase role="keyword">
virtual</phrase><phrase role="special"> ~</phrase><phrase role="identifier">Base</phrase><phrase role="special">()</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
virtual</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> =</phrase><phrase role="number"> 0</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
design. In principle, it should be possible to expose the interface for a 3rd
party library without changing it. It is not ideal to add anything to our class
<code><phrase role="identifier">Base</phrase></code>. Yet, when you have a virtual function that's going to be overridden in
Python and called polymorphically <emphasis role="bold">from C++</emphasis>, we'll need to add some
scaffoldings to make things work properly. What we'll do is write a class
wrapper that derives from <code><phrase role="identifier">Base</phrase></code> that will unintrusively hook into the virtual
functions so that a Python override may be called:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> wrapper</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">&gt;</phrase><phrase role="special">
{</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="keyword"> this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">)();</phrase><phrase role="special">
}</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
Notice too that in addition to inheriting from <code><phrase role="identifier">Base</phrase></code>, we also multiply-
inherited <code><phrase role="identifier">wrapper</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">&gt;</phrase></code> (See <ulink url="../../../v2/wrapper.html">Wrapper</ulink>). The
<code><phrase role="identifier">wrapper</phrase></code> template makes the job of wrapping classes that are meant to
overridden in Python, easier.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> MSVC6/7 Workaround<para/>
<para/>
If you are using Microsoft Visual C++ 6 or 7, you have to write <code><phrase role="identifier">f</phrase></code> as:<para/>
<para/>
<code><phrase role="keyword">return</phrase><phrase role="identifier"> call</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;(</phrase><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">).</phrase><phrase role="identifier">ptr</phrase><phrase role="special">());</phrase></code>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
BaseWrap's overridden virtual member function <code><phrase role="identifier">f</phrase></code> in effect calls the
corresponding method of the Python object through <code><phrase role="identifier">get_override</phrase></code>.</para>
<para>
Finally, exposing <code><phrase role="identifier">Base</phrase></code>:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Base&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> pure_virtual</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">))</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
<code><phrase role="identifier">pure_virtual</phrase></code> signals Boost.Python that the function <code><phrase role="identifier">f</phrase></code> is a pure virtual
function.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">member function and methods</emphasis><para/>
<para/>
Python, like
many object oriented languages uses the term <emphasis role="bold">methods</emphasis>. Methods
correspond roughly to C++'s <emphasis role="bold">member functions</emphasis></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="python.virtual_functions_with_default_implementations">
<title>Virtual Functions with Default Implementations</title>
<para>
We've seen in the previous section how classes with pure virtual functions are
wrapped using Boost.Python's <ulink url="../../../v2/wrapper.html">class wrapper</ulink>
facilities. If we wish to wrap <emphasis role="bold">non</emphasis>-pure-virtual functions instead, the
mechanism is a bit different.</para>
<para>
Recall that in the <link linkend="python.class_virtual_functions">previous section</link>, we
wrapped a class with a pure virtual function that we then implemented in C++, or
Python classes derived from it. Our base class:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
{</phrase><phrase role="keyword">
virtual</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> =</phrase><phrase role="number"> 0</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
had a pure virtual function <literal>f</literal>. If, however, its member function <literal>f</literal> was
not declared as pure virtual:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Base</phrase><phrase role="special">
{</phrase><phrase role="keyword">
virtual</phrase><phrase role="special"> ~</phrase><phrase role="identifier">Base</phrase><phrase role="special">()</phrase><phrase role="special"> {}</phrase><phrase role="keyword">
virtual</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="number"> 0</phrase><phrase role="special">;</phrase><phrase role="special"> }</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
We wrap it this way:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> BaseWrap</phrase><phrase role="special"> :</phrase><phrase role="identifier"> Base</phrase><phrase role="special">,</phrase><phrase role="identifier"> wrapper</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">&gt;</phrase><phrase role="special">
{</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">override</phrase><phrase role="identifier"> f</phrase><phrase role="special"> =</phrase><phrase role="keyword"> this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">get_override</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">))</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> f</phrase><phrase role="special">();</phrase><phrase role="comment"> // *note*
</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special">
}</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> default_f</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="keyword"> this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
Notice how we implemented <code><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase></code>. Now, we have to check if there is an
override for <code><phrase role="identifier">f</phrase></code>. If none, then we call <code><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">()</phrase></code>.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> MSVC6/7 Workaround<para/>
<para/>
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
with the <code><phrase role="special">*</phrase><phrase role="identifier">note</phrase><phrase role="special">*</phrase></code> as:<para/>
<para/>
<code><phrase role="keyword">return</phrase><phrase role="identifier"> call</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="keyword"> const</phrase><phrase role="special">*&gt;(</phrase><phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">());</phrase></code>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
Finally, exposing:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">,</phrase><phrase role="identifier"> boost</phrase><phrase role="special">::</phrase><phrase role="identifier">noncopyable</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Base&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">default_f</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
Take note that we expose both <code><phrase role="special">&amp;</phrase><phrase role="identifier">Base</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase></code> and <code><phrase role="special">&amp;</phrase><phrase role="identifier">BaseWrap</phrase><phrase role="special">::</phrase><phrase role="identifier">default_f</phrase></code>.
Boost.Python needs to keep track of 1) the dispatch function <literal>f</literal> and 2) the
forwarding function to its default implementation <literal>default_f</literal>. There's a
special <literal>def</literal> function for this purpose.</para>
<para>
In Python, the results would be as expected:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> base</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Base</phrase><phrase role="special">()</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="keyword"> class</phrase><phrase role="identifier"> Derived</phrase><phrase role="special">(</phrase><phrase role="identifier">Base</phrase><phrase role="special">):</phrase><phrase role="special">
...</phrase><phrase role="identifier"> def</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="special">
...</phrase><phrase role="keyword"> return</phrase><phrase role="number"> 42</phrase><phrase role="special">
...</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> derived</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Derived</phrase><phrase role="special">()</phrase>
</literal>
</programlisting>
<para>
Calling <literal>base.f()</literal>:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> base</phrase><phrase role="special">.</phrase><phrase role="identifier">f</phrase><phrase role="special">()</phrase><phrase role="number">
0</phrase>
</literal>
</programlisting>
<para>
Calling <literal>derived.f()</literal>:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> derived</phrase><phrase role="special">.</phrase><phrase role="identifier">f</phrase><phrase role="special">()</phrase><phrase role="number">
42</phrase>
</literal>
</programlisting>
</section>
<section id="python.class_operators_special_functions">
<title>Class Operators/Special Functions</title>
<anchor id="class_operators_special_functions.python_operators" /><bridgehead renderas="sect2">Python Operators</bridgehead><para>
C is well known for the abundance of operators. C++ extends this to the
extremes by allowing operator overloading. Boost.Python takes advantage of
this and makes it easy to wrap C++ operator-powered classes.</para>
<para>
Consider a file position class <literal>FilePos</literal> and a set of operators that take
on FilePos instances:</para>
<programlisting>
<literal>
<phrase role="keyword">class</phrase><phrase role="identifier"> FilePos</phrase><phrase role="special"> {</phrase><phrase role="comment"> /*...*/</phrase><phrase role="special"> };</phrase><phrase role="identifier">
FilePos</phrase><phrase role="keyword"> operator</phrase><phrase role="special">+(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">);</phrase><phrase role="identifier">
FilePos</phrase><phrase role="keyword"> operator</phrase><phrase role="special">+(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="identifier"> FilePos</phrase><phrase role="special">);</phrase><phrase role="keyword">
int</phrase><phrase role="keyword"> operator</phrase><phrase role="special">-(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">,</phrase><phrase role="identifier"> FilePos</phrase><phrase role="special">);</phrase><phrase role="identifier">
FilePos</phrase><phrase role="keyword"> operator</phrase><phrase role="special">-(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">);</phrase><phrase role="identifier">
FilePos</phrase><phrase role="special">&amp;</phrase><phrase role="keyword"> operator</phrase><phrase role="special">+=(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">&amp;,</phrase><phrase role="keyword"> int</phrase><phrase role="special">);</phrase><phrase role="identifier">
FilePos</phrase><phrase role="special">&amp;</phrase><phrase role="keyword"> operator</phrase><phrase role="special">-=(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">&amp;,</phrase><phrase role="keyword"> int</phrase><phrase role="special">);</phrase><phrase role="keyword">
bool</phrase><phrase role="keyword"> operator</phrase><phrase role="special">&lt;(</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">,</phrase><phrase role="identifier"> FilePos</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
The class and the various operators can be mapped to Python rather easily
and intuitively:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">FilePos</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;FilePos&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> +</phrase><phrase role="keyword"> int</phrase><phrase role="special">())</phrase><phrase role="comment"> // __add__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">()</phrase><phrase role="special"> +</phrase><phrase role="identifier"> self</phrase><phrase role="special">)</phrase><phrase role="comment"> // __radd__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> -</phrase><phrase role="identifier"> self</phrase><phrase role="special">)</phrase><phrase role="comment"> // __sub__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> -</phrase><phrase role="keyword"> int</phrase><phrase role="special">())</phrase><phrase role="comment"> // __sub__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> +=</phrase><phrase role="keyword"> int</phrase><phrase role="special">())</phrase><phrase role="comment"> // __iadd__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> -=</phrase><phrase role="identifier"> other</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier"> self</phrase><phrase role="special">);</phrase><phrase role="comment"> // __lt__
</phrase></literal>
</programlisting>
<para>
The code snippet above is very clear and needs almost no explanation at
all. It is virtually the same as the operators' signatures. Just take
note that <literal>self</literal> refers to FilePos object. Also, not every class <literal>T</literal> that
you might need to interact with in an operator expression is (cheaply)
default-constructible. You can use <literal>other&lt;T&gt;()</literal> in place of an actual
<literal>T</literal> instance when writing &quot;self expressions&quot;.</para>
<anchor id="class_operators_special_functions.special_methods" /><bridgehead renderas="sect2">Special Methods</bridgehead><para>
Python has a few more <emphasis>Special Methods</emphasis>. 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 <emphasis>special functions</emphasis>. Example:</para>
<programlisting>
<literal>
<phrase role="keyword">class</phrase><phrase role="identifier"> Rational</phrase><phrase role="special">
{</phrase><phrase role="keyword"> operator</phrase><phrase role="keyword"> double</phrase><phrase role="special">()</phrase><phrase role="keyword"> const</phrase><phrase role="special">;</phrase><phrase role="special"> };</phrase><phrase role="identifier">
Rational</phrase><phrase role="identifier"> pow</phrase><phrase role="special">(</phrase><phrase role="identifier">Rational</phrase><phrase role="special">,</phrase><phrase role="identifier"> Rational</phrase><phrase role="special">);</phrase><phrase role="identifier">
Rational</phrase><phrase role="identifier"> abs</phrase><phrase role="special">(</phrase><phrase role="identifier">Rational</phrase><phrase role="special">);</phrase><phrase role="identifier">
ostream</phrase><phrase role="special">&amp;</phrase><phrase role="keyword"> operator</phrase><phrase role="special">&lt;&lt;(</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&amp;,</phrase><phrase role="identifier">Rational</phrase><phrase role="special">);</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Rational</phrase><phrase role="special">&gt;()</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">float_</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">))</phrase><phrase role="comment"> // __float__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">pow</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="identifier"> other</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Rational</phrase><phrase role="special">&gt;))</phrase><phrase role="comment"> // __pow__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">abs</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">))</phrase><phrase role="comment"> // __abs__
</phrase><phrase role="special"> .</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">str</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">))</phrase><phrase role="comment"> // __str__
</phrase><phrase role="special"> ;</phrase>
</literal>
</programlisting>
<para>
Need we say more?</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> What is the business of <literal>operator&lt;&lt;</literal> <literal>.def(str(self))</literal>?
Well, the method <literal>str</literal> requires the <literal>operator&lt;&lt;</literal> to do its work (i.e.
<literal>operator&lt;&lt;</literal> is used by the method defined by def(str(self)).</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section></section>
<section id="python.functions">
<title>Functions</title>
<para>
In this chapter, we'll look at Boost.Python powered functions in closer
detail. We shall see some facilities to make exposing C++ functions to
Python safe from potential pifalls such as dangling pointers and
references. We shall also see facilities that will make it even easier for
us to expose C++ functions that take advantage of C++ features such as
overloading and default arguments.</para>
<blockquote><para><emphasis>Read on...</emphasis></para></blockquote><para>
But before you do, you might want to fire up Python 2.2 or later and type
<literal>&gt;&gt;&gt; import this</literal>.</para>
<programlisting><literal> &gt;&gt;&gt; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than <emphasis role="bold">right</emphasis> now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</literal></programlisting>
<section id="python.call_policies">
<title>Call Policies</title>
<para>
In C++, we often deal with arguments and return types such as pointers
and references. Such primitive types are rather, ummmm, low level and
they really don't tell us much. At the very least, we don't know the
owner of the pointer or the referenced object. No wonder languages
such as Java and Python never deal with such low level entities. In
C++, it's usually considered a good practice to use smart pointers
which exactly describe ownership semantics. Still, even good C++
interfaces use raw references and pointers sometimes, so Boost.Python
must deal with them. To do this, it may need your help. Consider the
following C++ function:</para>
<programlisting>
<literal>
<phrase role="identifier">X</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">Y</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> y</phrase><phrase role="special">,</phrase><phrase role="identifier"> Z</phrase><phrase role="special">*</phrase><phrase role="identifier"> z</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
How should the library wrap this function? A naive approach builds a
Python X object around result reference. This strategy might or might
not work out. Here's an example where it didn't</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special"> =</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">y</phrase><phrase role="special">,</phrase><phrase role="identifier"> z</phrase><phrase role="special">)</phrase>&nbsp;#<phrase role="identifier"> x</phrase><phrase role="identifier"> refers</phrase><phrase role="identifier"> to</phrase><phrase role="identifier"> some</phrase><phrase role="identifier"> C</phrase><phrase role="special">++</phrase><phrase role="identifier"> X</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> del</phrase><phrase role="identifier"> y</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">some_method</phrase><phrase role="special">()</phrase>&nbsp;#<phrase role="identifier"> CRASH</phrase><phrase role="special">!</phrase>
</literal>
</programlisting>
<para>
What's the problem?</para>
<para>
Well, what if f() was implemented as shown below:</para>
<programlisting>
<literal>
<phrase role="identifier">X</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">Y</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> y</phrase><phrase role="special">,</phrase><phrase role="identifier"> Z</phrase><phrase role="special">*</phrase><phrase role="identifier"> z</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
y</phrase><phrase role="special">.</phrase><phrase role="identifier">z</phrase><phrase role="special"> =</phrase><phrase role="identifier"> z</phrase><phrase role="special">;</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> y</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
The problem is that the lifetime of result X&amp; is tied to the lifetime
of y, because the f() returns a reference to a member of the y
object. This idiom is is not uncommon and perfectly acceptable in the
context of C++. However, Python users should not be able to crash the
system just by using our C++ interface. In this case deleting y will
invalidate the reference to X. We have a dangling reference.</para>
<para>
Here's what's happening:</para>
<orderedlist>
<listitem>
<literal>f</literal> is called passing in a reference to <literal>y</literal> and a pointer to <literal>z</literal>
</listitem><listitem>
A reference to <literal>y.x</literal> is returned
</listitem><listitem>
<literal>y</literal> is deleted. <literal>x</literal> is a dangling reference
</listitem><listitem>
<literal>x.some_method()</literal> is called
</listitem><listitem>
<emphasis role="bold">BOOM!</emphasis>
</listitem>
</orderedlist><para>
We could copy result into a new object:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">y</phrase><phrase role="special">,</phrase><phrase role="identifier"> z</phrase><phrase role="special">).</phrase><phrase role="identifier">set</phrase><phrase role="special">(</phrase><phrase role="number">42</phrase><phrase role="special">)</phrase>&nbsp;#<phrase role="identifier"> Result</phrase><phrase role="identifier"> disappears</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> y</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> No</phrase><phrase role="identifier"> crash</phrase><phrase role="special">,</phrase><phrase role="identifier"> but</phrase><phrase role="identifier"> still</phrase><phrase role="identifier"> bad</phrase><phrase role="number">
3.14</phrase>
</literal>
</programlisting>
<para>
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.</para>
<para>
Our problems do not end there. Suppose Y is implemented as follows:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> Y</phrase><phrase role="special">
{</phrase><phrase role="identifier">
X</phrase><phrase role="identifier"> x</phrase><phrase role="special">;</phrase><phrase role="identifier"> Z</phrase><phrase role="special">*</phrase><phrase role="identifier"> z</phrase><phrase role="special">;</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> z_value</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword"> return</phrase><phrase role="identifier"> z</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value</phrase><phrase role="special">();</phrase><phrase role="special"> }</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
Notice that the data member <literal>z</literal> is held by class Y using a raw
pointer. Now we have a potential dangling pointer problem inside Y:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special"> =</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">y</phrase><phrase role="special">,</phrase><phrase role="identifier"> z</phrase><phrase role="special">)</phrase>&nbsp;#<phrase role="identifier"> y</phrase><phrase role="identifier"> refers</phrase><phrase role="identifier"> to</phrase><phrase role="identifier"> z</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> del</phrase><phrase role="identifier"> z</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> Kill</phrase><phrase role="identifier"> the</phrase><phrase role="identifier"> z</phrase><phrase role="identifier"> object</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> y</phrase><phrase role="special">.</phrase><phrase role="identifier">z_value</phrase><phrase role="special">()</phrase>&nbsp;#<phrase role="identifier"> CRASH</phrase><phrase role="special">!</phrase>
</literal>
</programlisting>
<para>
For reference, here's the implementation of <literal>f</literal> again:</para>
<programlisting>
<literal>
<phrase role="identifier">X</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">Y</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> y</phrase><phrase role="special">,</phrase><phrase role="identifier"> Z</phrase><phrase role="special">*</phrase><phrase role="identifier"> z</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
y</phrase><phrase role="special">.</phrase><phrase role="identifier">z</phrase><phrase role="special"> =</phrase><phrase role="identifier"> z</phrase><phrase role="special">;</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> y</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Here's what's happening:</para>
<orderedlist>
<listitem>
<literal>f</literal> is called passing in a reference to <literal>y</literal> and a pointer to <literal>z</literal>
</listitem><listitem>
A pointer to <literal>z</literal> is held by <literal>y</literal>
</listitem><listitem>
A reference to <literal>y.x</literal> is returned
</listitem><listitem>
<literal>z</literal> is deleted. <literal>y.z</literal> is a dangling pointer
</listitem><listitem>
<literal>y.z_value()</literal> is called
</listitem><listitem>
<literal>z-&gt;value()</literal> is called
</listitem><listitem>
<emphasis role="bold">BOOM!</emphasis>
</listitem>
</orderedlist><anchor id="call_policies.call_policies" /><bridgehead renderas="sect2">Call Policies</bridgehead><para>
Call Policies may be used in situations such as the example detailed above.
In our example, <literal>return_internal_reference</literal> and <literal>with_custodian_and_ward</literal>
are our friends:</para>
<programlisting>
<literal>
<phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> f</phrase><phrase role="special">,</phrase><phrase role="identifier">
return_internal_reference</phrase><phrase role="special">&lt;</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase><phrase role="identifier">
with_custodian_and_ward</phrase><phrase role="special">&lt;</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase><phrase role="number"> 2</phrase><phrase role="special">&gt;</phrase><phrase role="special"> &gt;());</phrase>
</literal>
</programlisting>
<para>
What are the <literal>1</literal> and <literal>2</literal> parameters, you ask?</para>
<programlisting>
<literal>
<phrase role="identifier">return_internal_reference</phrase><phrase role="special">&lt;</phrase><phrase role="number">1</phrase>
</literal>
</programlisting>
<para>
Informs Boost.Python that the first argument, in our case <literal>Y&amp; y</literal>, is the
owner of the returned reference: <literal>X&amp;</literal>. The &quot;<literal>1</literal>&quot; simply specifies the
first argument. In short: &quot;return an internal reference <literal>X&amp;</literal> owned by the
1st argument <literal>Y&amp; y</literal>&quot;.</para>
<programlisting>
<literal>
<phrase role="identifier">with_custodian_and_ward</phrase><phrase role="special">&lt;</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase><phrase role="number"> 2</phrase><phrase role="special">&gt;</phrase>
</literal>
</programlisting>
<para>
Informs Boost.Python that the lifetime of the argument indicated by ward
(i.e. the 2nd argument: <literal>Z* z</literal>) is dependent on the lifetime of the
argument indicated by custodian (i.e. the 1st argument: <literal>Y&amp; y</literal>).</para>
<para>
It is also important to note that we have defined two policies above. Two
or more policies can be composed by chaining. Here's the general syntax:</para>
<programlisting>
<literal>
<phrase role="identifier">policy1</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">args</phrase><phrase role="special">...,</phrase><phrase role="identifier">
policy2</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">args</phrase><phrase role="special">...,</phrase><phrase role="identifier">
policy3</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">args</phrase><phrase role="special">...&gt;</phrase><phrase role="special"> &gt;</phrase><phrase role="special"> &gt;</phrase>
</literal>
</programlisting>
<para>
Here is the list of predefined call policies. A complete reference detailing
these can be found <ulink url="../../../v2/reference.html#models_of_call_policies">here</ulink>.</para>
<itemizedlist>
<listitem>
<emphasis role="bold">with_custodian_and_ward</emphasis><para/>
Ties lifetimes of the arguments
</listitem><listitem>
<emphasis role="bold">with_custodian_and_ward_postcall</emphasis><para/>
Ties lifetimes of the arguments and results
</listitem><listitem>
<emphasis role="bold">return_internal_reference</emphasis><para/>
Ties lifetime of one argument to that of result
</listitem><listitem>
<emphasis role="bold">return_value_policy&lt;T&gt; with T one of:</emphasis><para/>
</listitem><listitem>
<emphasis role="bold">reference_existing_object</emphasis><para/>
naive (dangerous) approach
</listitem><listitem>
<emphasis role="bold">copy_const_reference</emphasis><para/>
Boost.Python v1 approach
</listitem><listitem>
<emphasis role="bold">copy_non_const_reference</emphasis><para/>
</listitem><listitem>
<emphasis role="bold">manage_new_object</emphasis><para/>
Adopt a pointer and hold the instance
</listitem>
</itemizedlist><informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Remember the Zen, Luke:</emphasis><para/>
<para/>
&quot;Explicit is better than implicit&quot;<para/>
&quot;In the face of ambiguity, refuse the temptation to guess&quot;<para/>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="python.overloading">
<title>Overloading</title>
<para>
The following illustrates a scheme for manually wrapping an overloaded
member functions. Of course, the same technique can be applied to wrapping
overloaded non-member functions.</para>
<para>
We have here our C++ class:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> X</phrase><phrase role="special">
{</phrase><phrase role="keyword">
bool</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="keyword"> true</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase><phrase role="keyword">
bool</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="identifier"> b</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="keyword"> true</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase><phrase role="keyword">
bool</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="identifier"> b</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="identifier"> c</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="keyword"> true</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> b</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> c</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> a</phrase><phrase role="special"> +</phrase><phrase role="identifier"> b</phrase><phrase role="special"> +</phrase><phrase role="identifier"> c</phrase><phrase role="special">;</phrase><phrase role="special">
};</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
Class X has 4 overloaded functions. We shall start by introducing some
member function pointer variables:</para>
<programlisting>
<literal>
<phrase role="keyword">bool</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx1</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase><phrase role="keyword">
bool</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx2</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase><phrase role="keyword">
bool</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx3</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="special">)=</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase><phrase role="keyword">
int</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx4</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase>
</literal>
</programlisting>
<para>
With these in hand, we can proceed to define and wrap this for Python:</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx1</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx2</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx3</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx4</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
</section>
<section id="python.default_arguments">
<title>Default Arguments</title>
<para>
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
pointers carry no default argument info. Take a function <literal>f</literal> with default
arguments:</para>
<programlisting>
<literal>
<phrase role="keyword">int</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special"> =</phrase><phrase role="number"> 3.14</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="keyword"> const</phrase><phrase role="special">*</phrase><phrase role="special"> =</phrase><phrase role="string"> &quot;hello&quot;</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
But the type of a pointer to the function <literal>f</literal> has no information
about its default arguments:</para>
<programlisting>
<literal>
<phrase role="keyword">int</phrase><phrase role="special">(*</phrase><phrase role="identifier">g</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="keyword">char</phrase><phrase role="keyword"> const</phrase><phrase role="special">*)</phrase><phrase role="special"> =</phrase><phrase role="identifier"> f</phrase><phrase role="special">;</phrase><phrase role="comment"> // defaults lost!
</phrase></literal>
</programlisting>
<para>
When we pass this function pointer to the <literal>def</literal> function, there is no way
to retrieve the default arguments:</para>
<programlisting>
<literal>
<phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> f</phrase><phrase role="special">);</phrase><phrase role="comment"> // defaults lost!
</phrase></literal>
</programlisting>
<para>
Because of this, when wrapping C++ code, we had to resort to manual
wrapping as outlined in the <link linkend="python.overloading">previous section</link>, or
writing thin wrappers:</para>
<programlisting>
<literal>
<phrase role="comment">// write &quot;thin wrappers&quot;
</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> f1</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> x</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">);</phrase><phrase role="special"> }</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> f2</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> x</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="identifier"> y</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">,</phrase><phrase role="identifier">y</phrase><phrase role="special">);</phrase><phrase role="special"> }</phrase><phrase role="comment">
/*...*/
// in module init
</phrase><phrase role="identifier"> def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> f</phrase><phrase role="special">);</phrase><phrase role="comment"> // all arguments
</phrase><phrase role="identifier"> def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> f2</phrase><phrase role="special">);</phrase><phrase role="comment"> // two arguments
</phrase><phrase role="identifier"> def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> f1</phrase><phrase role="special">);</phrase><phrase role="comment"> // one argument
</phrase></literal>
</programlisting>
<para>
When you want to wrap functions (or member functions) that either:</para>
<itemizedlist>
<listitem>
have default arguments, or
</listitem><listitem>
are overloaded with a common sequence of initial arguments
</listitem>
</itemizedlist><anchor id="default_arguments.boost_python_function_overloads" /><bridgehead renderas="sect2">BOOST_PYTHON_FUNCTION_OVERLOADS</bridgehead><para>
Boost.Python now has a way to make it easier. For instance, given a function:</para>
<programlisting>
<literal>
<phrase role="keyword">int</phrase><phrase role="identifier"> foo</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="identifier"> b</phrase><phrase role="special"> =</phrase><phrase role="number"> 1</phrase><phrase role="special">,</phrase><phrase role="keyword"> unsigned</phrase><phrase role="identifier"> c</phrase><phrase role="special"> =</phrase><phrase role="number"> 2</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="identifier"> d</phrase><phrase role="special"> =</phrase><phrase role="number"> 3</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
The macro invocation:</para>
<programlisting>
<literal>
<phrase role="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</phrase><phrase role="special">(</phrase><phrase role="identifier">foo_overloads</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo</phrase><phrase role="special">,</phrase><phrase role="number"> 1</phrase><phrase role="special">,</phrase><phrase role="number"> 4</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
will automatically create the thin wrappers for us. This macro will create
a class <literal>foo_overloads</literal> that can be passed on to <literal>def(...)</literal>. The third
and fourth macro argument are the minimum arguments and maximum arguments,
respectively. In our <literal>foo</literal> function the minimum number of arguments is 1
and the maximum number of arguments is 4. The <literal>def(...)</literal> function will
automatically add all the foo variants for us:</para>
<programlisting>
<literal>
<phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;foo&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo_overloads</phrase><phrase role="special">());</phrase>
</literal>
</programlisting>
<anchor id="default_arguments.boost_python_member_function_overloads" /><bridgehead renderas="sect2">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</bridgehead><para>
Objects here, objects there, objects here there everywhere. More frequently
than anything else, we need to expose member functions of our classes to
Python. Then again, we have the same inconveniences as before when default
arguments or overloads with a common sequence of initial arguments come
into play. Another macro is provided to make this a breeze.</para>
<para>
Like <literal>BOOST_PYTHON_FUNCTION_OVERLOADS</literal>,
<literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> may be used to automatically create
the thin wrappers for wrapping member functions. Let's have an example:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> george</phrase><phrase role="special">
{</phrase><phrase role="keyword">
void</phrase><phrase role="identifier">
wack_em</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> b</phrase><phrase role="special"> =</phrase><phrase role="number"> 0</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="identifier"> c</phrase><phrase role="special"> =</phrase><phrase role="char"> 'x'</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase><phrase role="special">
};</phrase>
</literal>
</programlisting>
<para>
The macro invocation:</para>
<programlisting>
<literal>
<phrase role="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</phrase><phrase role="special">(</phrase><phrase role="identifier">george_overloads</phrase><phrase role="special">,</phrase><phrase role="identifier"> wack_em</phrase><phrase role="special">,</phrase><phrase role="number"> 1</phrase><phrase role="special">,</phrase><phrase role="number"> 3</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
will generate a set of thin wrappers for george's <literal>wack_em</literal> member function
accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and
fourth macro argument). The thin wrappers are all enclosed in a class named
<literal>george_overloads</literal> that can then be used as an argument to <literal>def(...)</literal>:</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wack_em&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">george</phrase><phrase role="special">::</phrase><phrase role="identifier">wack_em</phrase><phrase role="special">,</phrase><phrase role="identifier"> george_overloads</phrase><phrase role="special">());</phrase>
</literal>
</programlisting>
<para>
See the <ulink url="../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec">overloads reference</ulink>
for details.</para>
<anchor id="default_arguments.init_and_optional" /><bridgehead renderas="sect2">init and optional</bridgehead><para>
A similar facility is provided for class constructors, again, with
default arguments or a sequence of overloads. Remember <literal>init&lt;...&gt;</literal>? For example,
given a class X with a constructor:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> X</phrase><phrase role="special">
{</phrase><phrase role="identifier">
X</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="identifier"> b</phrase><phrase role="special"> =</phrase><phrase role="char"> 'D'</phrase><phrase role="special">,</phrase><phrase role="identifier"> std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="identifier"> c</phrase><phrase role="special"> =</phrase><phrase role="string"> &quot;constructor&quot;</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="identifier"> d</phrase><phrase role="special"> =</phrase><phrase role="number"> 0.0</phrase><phrase role="special">);</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
You can easily add this constructor to Boost.Python in one shot:</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="identifier">init</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="identifier"> optional</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">,</phrase><phrase role="identifier"> std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">&gt;</phrase><phrase role="special"> &gt;())</phrase>
</literal>
</programlisting>
<para>
Notice the use of <literal>init&lt;...&gt;</literal> and <literal>optional&lt;...&gt;</literal> to signify the default
(optional arguments).</para>
</section>
<section id="python.auto_overloading">
<title>Auto-Overloading</title>
<para>
It was mentioned in passing in the previous section that
<literal>BOOST_PYTHON_FUNCTION_OVERLOADS</literal> and <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal>
can also be used for overloaded functions and member functions with a
common sequence of initial arguments. Here is an example:</para>
<programlisting>
<literal>
<phrase role="keyword">void</phrase><phrase role="identifier"> foo</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> foo</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="identifier"> a</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> foo</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> b</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> foo</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="identifier"> a</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> b</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="identifier"> c</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/*...*/</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Like in the previous section, we can generate thin wrappers for these
overloaded functions in one-shot:</para>
<programlisting>
<literal>
<phrase role="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</phrase><phrase role="special">(</phrase><phrase role="identifier">foo_overloads</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo</phrase><phrase role="special">,</phrase><phrase role="number"> 0</phrase><phrase role="special">,</phrase><phrase role="number"> 3</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
Then...</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;foo&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo</phrase><phrase role="special">,</phrase><phrase role="identifier"> foo_overloads</phrase><phrase role="special">());</phrase>
</literal>
</programlisting>
<para>
Notice though that we have a situation now where we have a minimum of zero
(0) arguments and a maximum of 3 arguments.</para>
<anchor id="auto_overloading.manual_wrapping" /><bridgehead renderas="sect2">Manual Wrapping</bridgehead><para>
It is important to emphasize however that <emphasis role="bold">the overloaded functions must
have a common sequence of initial arguments</emphasis>. Otherwise, our scheme above
will not work. If this is not the case, we have to wrap our functions
<link linkend="python.overloading">manually</link>.</para>
<para>
Actually, we can mix and match manual wrapping of overloaded functions and
automatic wrapping through <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> and
its sister, <literal>BOOST_PYTHON_FUNCTION_OVERLOADS</literal>. Following up on our example
presented in the section <link linkend="python.overloading">on overloading</link>, since the
first 4 overload functins have a common sequence of initial arguments, we
can use <literal>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</literal> to automatically wrap the
first three of the <literal>def</literal>s and manually wrap just the last. Here's
how we'll do this:</para>
<programlisting>
<literal>
<phrase role="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</phrase><phrase role="special">(</phrase><phrase role="identifier">xf_overloads</phrase><phrase role="special">,</phrase><phrase role="identifier"> f</phrase><phrase role="special">,</phrase><phrase role="number"> 1</phrase><phrase role="special">,</phrase><phrase role="number"> 4</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
Create a member function pointers as above for both X::f overloads:</para>
<programlisting>
<literal>
<phrase role="keyword">bool</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx1</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">,</phrase><phrase role="keyword"> char</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase><phrase role="keyword">
int</phrase><phrase role="special"> (</phrase><phrase role="identifier">X</phrase><phrase role="special">::*</phrase><phrase role="identifier">fx2</phrase><phrase role="special">)(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">f</phrase><phrase role="special">;</phrase>
</literal>
</programlisting>
<para>
Then...</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx1</phrase><phrase role="special">,</phrase><phrase role="identifier"> xf_overloads</phrase><phrase role="special">());</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;f&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> fx2</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
</section></section>
<section id="python.object">
<title> Object Interface</title>
<para>
Python is dynamically typed, unlike C++ which is statically typed. Python
variables may hold an integer, a float, list, dict, tuple, str, long etc.,
among other things. In the viewpoint of Boost.Python and C++, these
Pythonic variables are just instances of class <literal>object</literal>. We shall see in
this chapter how to deal with Python objects.</para>
<para>
As mentioned, one of the goals of Boost.Python is to provide a
bidirectional mapping between C++ and Python while maintaining the Python
feel. Boost.Python C++ <literal>object</literal>s are as close as possible to Python. This
should minimize the learning curve significantly.</para>
<para>
<inlinemediaobject><imageobject><imagedata fileref="images/python.png"></imagedata></imageobject></inlinemediaobject></para>
<section id="python.basic_interface">
<title>Basic Interface</title>
<para>
Class <literal>object</literal> wraps <literal>PyObject*</literal>. All the intricacies of dealing with
<literal>PyObject</literal>s such as managing reference counting are handled by the
<literal>object</literal> class. C++ object interoperability is seamless. Boost.Python C++
<literal>object</literal>s can in fact be explicitly constructed from any C++ object.</para>
<para>
To illustrate, this Python code snippet:</para>
<programlisting>
<literal>
<phrase role="identifier">def</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">,</phrase><phrase role="identifier"> y</phrase><phrase role="special">):</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">y</phrase><phrase role="special"> ==</phrase><phrase role="char"> 'foo'</phrase><phrase role="special">):</phrase><phrase role="identifier">
x</phrase><phrase role="special">[</phrase><phrase role="number">3</phrase><phrase role="special">:</phrase><phrase role="number">7</phrase><phrase role="special">]</phrase><phrase role="special"> =</phrase><phrase role="char"> 'bar'</phrase><phrase role="keyword">
else</phrase><phrase role="special">:</phrase><phrase role="identifier">
x</phrase><phrase role="special">.</phrase><phrase role="identifier">items</phrase><phrase role="special"> +=</phrase><phrase role="identifier"> y</phrase><phrase role="special">(</phrase><phrase role="number">3</phrase><phrase role="special">,</phrase><phrase role="identifier"> x</phrase><phrase role="special">)</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> x</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> getfunc</phrase><phrase role="special">():</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> f</phrase><phrase role="special">;</phrase>
</literal>
</programlisting>
<para>
Can be rewritten in C++ using Boost.Python facilities this way:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">object</phrase><phrase role="identifier"> x</phrase><phrase role="special">,</phrase><phrase role="identifier"> object</phrase><phrase role="identifier"> y</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">y</phrase><phrase role="special"> ==</phrase><phrase role="string"> &quot;foo&quot;</phrase><phrase role="special">)</phrase><phrase role="identifier">
x</phrase><phrase role="special">.</phrase><phrase role="identifier">slice</phrase><phrase role="special">(</phrase><phrase role="number">3</phrase><phrase role="special">,</phrase><phrase role="number">7</phrase><phrase role="special">)</phrase><phrase role="special"> =</phrase><phrase role="string"> &quot;bar&quot;</phrase><phrase role="special">;</phrase><phrase role="keyword">
else</phrase><phrase role="identifier">
x</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;items&quot;</phrase><phrase role="special">)</phrase><phrase role="special"> +=</phrase><phrase role="identifier"> y</phrase><phrase role="special">(</phrase><phrase role="number">3</phrase><phrase role="special">,</phrase><phrase role="identifier"> x</phrase><phrase role="special">);</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> x</phrase><phrase role="special">;</phrase><phrase role="special">
}</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> getfunc</phrase><phrase role="special">()</phrase><phrase role="special"> {</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> object</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">);</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Apart from cosmetic differences due to the fact that we are writing the
code in C++, the look and feel should be immediately apparent to the Python
coder.</para>
</section>
<section id="python.derived_object_types">
<title>Derived Object types</title>
<para>
Boost.Python comes with a set of derived <literal>object</literal> types corresponding to
that of Python's:</para>
<itemizedlist>
<listitem>
list
</listitem><listitem>
dict
</listitem><listitem>
tuple
</listitem><listitem>
str
</listitem><listitem>
long_
</listitem><listitem>
enum
</listitem>
</itemizedlist><para>
These derived <literal>object</literal> types act like real Python types. For instance:</para>
<programlisting>
<literal>
<phrase role="identifier">str</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase><phrase role="special"> ==&gt;</phrase><phrase role="string"> &quot;1&quot;</phrase>
</literal>
</programlisting>
<para>
Wherever appropriate, a particular derived <literal>object</literal> has corresponding
Python type's methods. For instance, <literal>dict</literal> has a <literal>keys()</literal> method:</para>
<programlisting>
<literal>
<phrase role="identifier">d</phrase><phrase role="special">.</phrase><phrase role="identifier">keys</phrase><phrase role="special">()</phrase>
</literal>
</programlisting>
<para>
<literal>make_tuple</literal> is provided for declaring <emphasis>tuple literals</emphasis>. Example:</para>
<programlisting>
<literal>
<phrase role="identifier">make_tuple</phrase><phrase role="special">(</phrase><phrase role="number">123</phrase><phrase role="special">,</phrase><phrase role="char"> 'D'</phrase><phrase role="special">,</phrase><phrase role="string"> &quot;Hello, World&quot;</phrase><phrase role="special">,</phrase><phrase role="number"> 0.0</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
In C++, when Boost.Python <literal>object</literal>s are used as arguments to functions,
subtype matching is required. For example, when a function <literal>f</literal>, as
declared below, is wrapped, it will only accept instances of Python's
<literal>str</literal> type and subtypes.</para>
<programlisting>
<literal>
<phrase role="keyword">void</phrase><phrase role="identifier"> f</phrase><phrase role="special">(</phrase><phrase role="identifier">str</phrase><phrase role="identifier"> name</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> n2</phrase><phrase role="special"> =</phrase><phrase role="identifier"> name</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;upper&quot;</phrase><phrase role="special">)();</phrase><phrase role="comment"> // NAME = name.upper()
</phrase><phrase role="identifier"> str</phrase><phrase role="identifier"> NAME</phrase><phrase role="special"> =</phrase><phrase role="identifier"> name</phrase><phrase role="special">.</phrase><phrase role="identifier">upper</phrase><phrase role="special">();</phrase><phrase role="comment"> // better
</phrase><phrase role="identifier"> object</phrase><phrase role="identifier"> msg</phrase><phrase role="special"> =</phrase><phrase role="string"> &quot;%s is bigger than %s&quot;</phrase><phrase role="special"> %</phrase><phrase role="identifier"> make_tuple</phrase><phrase role="special">(</phrase><phrase role="identifier">NAME</phrase><phrase role="special">,</phrase><phrase role="identifier">name</phrase><phrase role="special">);</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
In finer detail:</para>
<programlisting>
<literal>
<phrase role="identifier">str</phrase><phrase role="identifier"> NAME</phrase><phrase role="special"> =</phrase><phrase role="identifier"> name</phrase><phrase role="special">.</phrase><phrase role="identifier">upper</phrase><phrase role="special">();</phrase>
</literal>
</programlisting>
<para>
Illustrates that we provide versions of the str type's methods as C++
member functions.</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> msg</phrase><phrase role="special"> =</phrase><phrase role="string"> &quot;%s is bigger than %s&quot;</phrase><phrase role="special"> %</phrase><phrase role="identifier"> make_tuple</phrase><phrase role="special">(</phrase><phrase role="identifier">NAME</phrase><phrase role="special">,</phrase><phrase role="identifier">name</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
Demonstrates that you can write the C++ equivalent of <literal>&quot;format&quot; % x,y,z</literal>
in Python, which is useful since there's no easy way to do that in std C++.</para>
<para>
<inlinemediaobject><imageobject><imagedata fileref="images/alert.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Beware</emphasis> the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.</para>
<para>
Python:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> d</phrase><phrase role="special"> =</phrase><phrase role="identifier"> dict</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">.</phrase><phrase role="identifier">__dict__</phrase><phrase role="special">)</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> copies</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">__dict__</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> d</phrase><phrase role="special">[</phrase><phrase role="char">'whatever'</phrase><phrase role="special">]</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> modifies</phrase><phrase role="identifier"> the</phrase><phrase role="identifier"> copy</phrase>
</literal>
</programlisting>
<para>
C++:</para>
<programlisting>
<literal>
<phrase role="identifier">dict</phrase><phrase role="identifier"> d</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__dict__&quot;</phrase><phrase role="special">));</phrase>&nbsp;&nbsp;#<phrase role="identifier"> copies</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">__dict__</phrase><phrase role="identifier">
d</phrase><phrase role="special">[</phrase><phrase role="char">'whatever'</phrase><phrase role="special">]</phrase><phrase role="special"> =</phrase><phrase role="number"> 3</phrase><phrase role="special">;</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> modifies</phrase><phrase role="identifier"> the</phrase><phrase role="identifier"> copy</phrase>
</literal>
</programlisting>
<anchor id="derived_object_types.class__lt_t_gt__as_objects" /><bridgehead renderas="sect2">class_&lt;T&gt; as objects</bridgehead><para>
Due to the dynamic nature of Boost.Python objects, any <literal>class_&lt;T&gt;</literal> may
also be one of these types! The following code snippet wraps the class
(type) object.</para>
<para>
We can use this to create wrapped instances. Example:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> vec345</phrase><phrase role="special"> =</phrase><phrase role="special"> (</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Vec2</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Vec2&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> init</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="keyword"> double</phrase><phrase role="special">&gt;())</phrase><phrase role="special">
.</phrase><phrase role="identifier">def_readonly</phrase><phrase role="special">(</phrase><phrase role="string">&quot;length&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Point</phrase><phrase role="special">::</phrase><phrase role="identifier">length</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def_readonly</phrase><phrase role="special">(</phrase><phrase role="string">&quot;angle&quot;</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">Point</phrase><phrase role="special">::</phrase><phrase role="identifier">angle</phrase><phrase role="special">)</phrase><phrase role="special">
)(</phrase><phrase role="number">3.0</phrase><phrase role="special">,</phrase><phrase role="number"> 4.0</phrase><phrase role="special">);</phrase><phrase role="identifier">
assert</phrase><phrase role="special">(</phrase><phrase role="identifier">vec345</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;length&quot;</phrase><phrase role="special">)</phrase><phrase role="special"> ==</phrase><phrase role="number"> 5.0</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
</section>
<section id="python.extracting_c___objects">
<title>Extracting C++ objects</title>
<para>
At some point, we will need to get C++ values out of object instances. This
can be achieved with the <literal>extract&lt;T&gt;</literal> function. Consider the following:</para>
<programlisting>
<literal>
<phrase role="keyword">double</phrase><phrase role="identifier"> x</phrase><phrase role="special"> =</phrase><phrase role="identifier"> o</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;length&quot;</phrase><phrase role="special">);</phrase><phrase role="comment"> // compile error
</phrase></literal>
</programlisting>
<para>
In the code above, we got a compiler error because Boost.Python
<literal>object</literal> can't be implicitly converted to <literal>double</literal>s. Instead, what
we wanted to do above can be achieved by writing:</para>
<programlisting>
<literal>
<phrase role="keyword">double</phrase><phrase role="identifier"> l</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">o</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;length&quot;</phrase><phrase role="special">));</phrase><phrase role="identifier">
Vec2</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> v</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Vec2</phrase><phrase role="special">&amp;&gt;(</phrase><phrase role="identifier">o</phrase><phrase role="special">);</phrase><phrase role="identifier">
assert</phrase><phrase role="special">(</phrase><phrase role="identifier">l</phrase><phrase role="special"> ==</phrase><phrase role="identifier"> v</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">());</phrase>
</literal>
</programlisting>
<para>
The first line attempts to extract the &quot;length&quot; attribute of the
Boost.Python <literal>object</literal> <literal>o</literal>. The second line attempts to <emphasis>extract</emphasis> the
<literal>Vec2</literal> object from held by the Boost.Python <literal>object</literal> <literal>o</literal>.</para>
<para>
Take note that we said &quot;attempt to&quot; above. What if the Boost.Python
<literal>object</literal> <literal>o</literal> does not really hold a <literal>Vec2</literal> type? This is certainly
a possibility considering the dynamic nature of Python <literal>object</literal>s. To
be on the safe side, if the C++ type can't be extracted, an
appropriate exception is thrown. To avoid an exception, we need to
test for extractibility:</para>
<programlisting>
<literal>
<phrase role="identifier">extract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Vec2</phrase><phrase role="special">&amp;&gt;</phrase><phrase role="identifier"> x</phrase><phrase role="special">(</phrase><phrase role="identifier">o</phrase><phrase role="special">);</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">x</phrase><phrase role="special">.</phrase><phrase role="identifier">check</phrase><phrase role="special">())</phrase><phrase role="special"> {</phrase><phrase role="identifier">
Vec2</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> v</phrase><phrase role="special"> =</phrase><phrase role="identifier"> x</phrase><phrase role="special">();</phrase><phrase role="special"> ...</phrase>
</literal>
</programlisting>
<para>
<inlinemediaobject><imageobject><imagedata fileref="images/tip.png"></imagedata></imageobject></inlinemediaobject> The astute reader might have noticed that the <literal>extract&lt;T&gt;</literal>
facility in fact solves the mutable copying problem:</para>
<programlisting>
<literal>
<phrase role="identifier">dict</phrase><phrase role="identifier"> d</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">dict</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">x</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__dict__&quot;</phrase><phrase role="special">));</phrase><phrase role="identifier">
d</phrase><phrase role="special">[</phrase><phrase role="char">'whatever'</phrase><phrase role="special">]</phrase><phrase role="special"> =</phrase><phrase role="number"> 3</phrase><phrase role="special">;</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> modifies</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">__dict__</phrase><phrase role="special"> !</phrase>
</literal>
</programlisting>
</section>
<section id="python.enums">
<title>Enums</title>
<para>
Boost.Python has a nifty facility to capture and wrap C++ enums. While
Python has no <literal>enum</literal> type, we'll often want to expose our C++ enums to
Python as an <literal>int</literal>. Boost.Python's enum facility makes this easy while
taking care of the proper conversions from Python's dynamic typing to C++'s
strong static typing (in C++, ints cannot be implicitly converted to
enums). To illustrate, given a C++ enum:</para>
<programlisting>
<literal>
<phrase role="keyword">enum</phrase><phrase role="identifier"> choice</phrase><phrase role="special"> {</phrase><phrase role="identifier"> red</phrase><phrase role="special">,</phrase><phrase role="identifier"> blue</phrase><phrase role="special"> };</phrase>
</literal>
</programlisting>
<para>
the construct:</para>
<programlisting>
<literal>
<phrase role="identifier">enum_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">choice</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;choice&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">value</phrase><phrase role="special">(</phrase><phrase role="string">&quot;red&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> red</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">value</phrase><phrase role="special">(</phrase><phrase role="string">&quot;blue&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> blue</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
<para>
can be used to expose to Python. The new enum type is created in the
current <literal>scope()</literal>, which is usually the current module. The snippet above
creates a Python class derived from Python's <literal>int</literal> type which is
associated with the C++ type passed as its first parameter.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">what is a scope?</emphasis><para/>
<para/>
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
attributes. Details can be found <ulink url="../../../v2/scope.html">here</ulink>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
You can access those values in Python as</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> my_module</phrase><phrase role="special">.</phrase><phrase role="identifier">choice</phrase><phrase role="special">.</phrase><phrase role="identifier">red</phrase><phrase role="identifier">
my_module</phrase><phrase role="special">.</phrase><phrase role="identifier">choice</phrase><phrase role="special">.</phrase><phrase role="identifier">red</phrase>
</literal>
</programlisting>
<para>
where my_module is the module where the enum is declared. You can also
create a new scope around a class:</para>
<programlisting>
<literal>
<phrase role="identifier">scope</phrase><phrase role="identifier"> in_X</phrase><phrase role="special"> =</phrase><phrase role="identifier"> class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;X&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="special"> ...</phrase><phrase role="special"> )</phrase><phrase role="special">
.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="special"> ...</phrase><phrase role="special"> )</phrase><phrase role="special">
;</phrase><phrase role="comment">
// Expose X::nested as X.nested
</phrase><phrase role="identifier">enum_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">::</phrase><phrase role="identifier">nested</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;nested&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">value</phrase><phrase role="special">(</phrase><phrase role="string">&quot;red&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> red</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">value</phrase><phrase role="special">(</phrase><phrase role="string">&quot;blue&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> blue</phrase><phrase role="special">)</phrase><phrase role="special">
;</phrase>
</literal>
</programlisting>
</section></section>
<section id="python.embedding">
<title>Embedding</title>
<para>
By now you should know how to use Boost.Python to call your C++ code from
Python. However, sometimes you may need to do the reverse: call Python code
from the C++-side. This requires you to <emphasis>embed</emphasis> the Python interpreter
into your C++ program.</para>
<para>
Currently, Boost.Python does not directly support everything you'll need
when embedding. Therefore you'll need to use the
<ulink url="http://www.python.org/doc/current/api/api.html">Python/C API</ulink> to fill in
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... <inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
<anchor id="embedding.building_embedded_programs" /><bridgehead renderas="sect2">Building embedded programs</bridgehead><para>
To be able to use embedding in your programs, they have to be linked to
both Boost.Python's and Python's static link library.</para>
<para>
Boost.Python's static link library comes in two variants. Both are located
in Boost's <literal>/libs/python/build/bin-stage</literal> subdirectory. On Windows, the
variants are called <literal>boost_python.lib</literal> (for release builds) and
<literal>boost_python_debug.lib</literal> (for debugging). If you can't find the libraries,
you probably haven't built Boost.Python yet. See
<ulink url="../../../building.html">Building and Testing</ulink> on how to do this.</para>
<para>
Python's static link library can be found in the <literal>/libs</literal> subdirectory of
your Python directory. On Windows it is called pythonXY.lib where X.Y is
your major Python version number.</para>
<para>
Additionally, Python's <literal>/include</literal> subdirectory has to be added to your
include path.</para>
<para>
In a Jamfile, all the above boils down to:</para>
<programlisting><literal> projectroot c:\projects\embedded_program ; # location of the program
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
exe embedded_program # name of the executable
: #sources
embedded_program.cpp
: # requirements
&lt;find-library&gt;boost_python &lt;library-path&gt;c:\boost\libs\python
$(PYTHON_PROPERTIES)
&lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
</literal></programlisting><anchor id="embedding.getting_started" /><bridgehead renderas="sect2">Getting started</bridgehead><para>
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:</para>
<orderedlist>
<listitem>
#include <literal>&lt;boost/python.hpp&gt;</literal><para/>
<para/>
</listitem><listitem>
Call <ulink url="http://www.python.org/doc/current/api/initialization.html#l2h-652">Py_Initialize</ulink>() to start the interpreter and create the <literal><emphasis role="underline">_main</emphasis>_</literal> module.<para/>
<para/>
</listitem><listitem>
Call other Python C API routines to use the interpreter.<para/>
<para/>
</listitem><listitem>
Call <ulink url="http://www.python.org/doc/current/api/initialization.html#l2h-656">Py_Finalize</ulink>() to stop the interpreter and release its resources.
</listitem>
</orderedlist><para>
(Of course, there can be other C++ code between all of these steps.)</para>
<blockquote><para><emphasis><emphasis role="bold">Now that we can embed the interpreter in our programs, lets see how to put it to use...</emphasis></emphasis></para></blockquote>
<section id="python.using_the_interpreter">
<title>Using the interpreter</title>
<para>
As you probably already know, objects in Python are reference-counted.
Naturally, the <literal>PyObject</literal>s of the Python/C API are also reference-counted.
There is a difference however. While the reference-counting is fully
automatic in Python, the Python/C API requires you to do it
<ulink url="http://www.python.org/doc/current/api/refcounts.html">by hand</ulink>. This is
messy and especially hard to get right in the presence of C++ exceptions.
Fortunately Boost.Python provides the <ulink url="../../../v2/handle.html">handle</ulink> and
<ulink url="../../../v2/object.html">object</ulink> class templates to automate the process.</para>
<anchor id="using_the_interpreter.reference_counting_handles_and_objects" /><bridgehead renderas="sect2">Reference-counting handles and objects</bridgehead><para>
There are two ways in which a function in the Python/C API can return a
<literal>PyObject*</literal>: as a <emphasis>borrowed reference</emphasis> or as a <emphasis>new reference</emphasis>. Which of
these a function uses, is listed in that function's documentation. The two
require slightely different approaches to reference-counting but both can
be 'handled' by Boost.Python.</para>
<para>
For a function returning a <emphasis>borrowed reference</emphasis> we'll have to tell the
<literal>handle</literal> that the <literal>PyObject*</literal> is borrowed with the aptly named
<ulink url="../../../v2/handle.html#borrowed-spec">borrowed</ulink> function. Two functions
returning borrowed references are <ulink url="http://www.python.org/doc/current/api/importing.html#l2h-125">PyImport_AddModule</ulink> and <ulink url="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594">PyModule_GetDict</ulink>.
The former returns a reference to an already imported module, the latter
retrieves a module's namespace dictionary. Let's use them to retrieve the
namespace of the <literal><emphasis role="underline">_main</emphasis>_</literal> module:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">((</phrase><phrase role="identifier">
handle</phrase><phrase role="special">&lt;&gt;(</phrase><phrase role="identifier">borrowed</phrase><phrase role="special">(</phrase><ulink url="http://www.python.org/doc/current/api/importing.html#l2h-125">PyImport_AddModule</ulink><phrase role="special">(</phrase><phrase role="string">&quot;__main__&quot;</phrase><phrase role="special">)))));</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special"> =</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__dict__&quot;</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
For a function returning a <emphasis>new reference</emphasis> we can just create a <literal>handle</literal>
out of the raw <literal>PyObject*</literal> without wrapping it in a call to borrowed. One
such function that returns a new reference is <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> which we'll
discuss in the next section.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Handle is a class <emphasis>template</emphasis>, so why haven't we been using any template parameters?</emphasis><para/>
<para/>
<literal>handle</literal> has a single template parameter specifying the type of the managed object. This type is <literal>PyObject</literal> 99% of the time, so the parameter was defaulted to <literal>PyObject</literal> for convenience. Therefore we can use the shorthand <literal>handle&lt;&gt;</literal> instead of the longer, but equivalent, <literal>handle&lt;PyObject&gt;</literal>.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<anchor id="using_the_interpreter.running_python_code" /><bridgehead renderas="sect2">Running Python code</bridgehead><para>
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
functions <ulink url="http://www.python.org/doc/current/api/veryhigh.html">here</ulink>. They
all work similarly so we will look at only one of them, namely:</para>
<programlisting>
<literal>
<phrase role="identifier">PyObject</phrase><phrase role="special">*</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special"> *</phrase><phrase role="identifier">str</phrase><phrase role="special">,</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> start</phrase><phrase role="special">,</phrase><phrase role="identifier"> PyObject</phrase><phrase role="special"> *</phrase><phrase role="identifier">globals</phrase><phrase role="special">,</phrase><phrase role="identifier"> PyObject</phrase><phrase role="special"> *</phrase><phrase role="identifier">locals</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> takes the code to execute as a null-terminated (C-style)
string in its <literal>str</literal> parameter. The function returns a new reference to a
Python object. Which object is returned depends on the <literal>start</literal> paramater.</para>
<para>
The <literal>start</literal> parameter is the start symbol from the Python grammar to use
for interpreting the code. The possible values are:</para>
<informaltable frame="all">
<bridgehead renderas="sect4"><phrase role="table-title">Start symbols</phrase></bridgehead>
<tgroup cols="2">
<thead><row><entry><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink></entry><entry>for interpreting isolated expressions</entry></row>
</thead>
<tbody>
<row><entry><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">Py_file_input</ulink></entry><entry>for interpreting sequences of statements</entry></row>
<row><entry><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">Py_single_input</ulink></entry><entry>for interpreting a single statement</entry></row>
</tbody>
</tgroup>
</informaltable>
<para>
When using <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink>, the input string must contain a single expression
and its result is returned. When using <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">Py_file_input</ulink>, the string can
contain an abitrary number of statements and None is returned.
<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">Py_single_input</ulink> works in the same way as <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">Py_file_input</ulink> but only accepts a
single statement.</para>
<para>
Lastly, the <literal>globals</literal> and <literal>locals</literal> parameters are Python dictionaries
containing the globals and locals of the context in which to run the code.
For most intents and purposes you can use the namespace dictionary of the
<literal><emphasis role="underline">_main</emphasis>_</literal> module for both parameters.</para>
<para>
We have already seen how to get the <literal><emphasis role="underline">_main</emphasis>_</literal> module's namespace so let's
run some Python code in it:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">((</phrase><phrase role="identifier">
handle</phrase><phrase role="special">&lt;&gt;(</phrase><phrase role="identifier">borrowed</phrase><phrase role="special">(</phrase><ulink url="http://www.python.org/doc/current/api/importing.html#l2h-125">PyImport_AddModule</ulink><phrase role="special">(</phrase><phrase role="string">&quot;__main__&quot;</phrase><phrase role="special">)))));</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special"> =</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__dict__&quot;</phrase><phrase role="special">);</phrase><phrase role="identifier">
handle</phrase><phrase role="special">&lt;&gt;</phrase><phrase role="identifier"> ignored</phrase><phrase role="special">((</phrase><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="string">
&quot;hello = file('hello.txt', 'w')\n&quot;</phrase><phrase role="string">
&quot;hello.write('Hello world!')\n&quot;</phrase><phrase role="string">
&quot;hello.close()&quot;</phrase><phrase role="special">
,</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">Py_file_input</ulink><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()</phrase><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">())</phrase><phrase role="special">
));</phrase>
</literal>
</programlisting>
<para>
Because the Python/C API doesn't know anything about <literal>object</literal>s, we used
the object's <literal>ptr</literal> member function to retrieve the <literal>PyObject*</literal>.</para>
<para>
This should create a file called 'hello.txt' in the current directory
containing a phrase that is well-known in programming circles.</para>
<para>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that we wrap the return value of <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> in a
(nameless) <literal>handle</literal> even though we are not interested in it. If we didn't
do this, the the returned object would be kept alive unnecessarily. Unless
you want to be a Dr. Frankenstein, always wrap <literal>PyObject*</literal>s in <literal>handle</literal>s.</para>
<anchor id="using_the_interpreter.beyond_handles" /><bridgehead renderas="sect2">Beyond handles</bridgehead><para>
It's nice that <literal>handle</literal> manages the reference counting details for us, but
other than that it doesn't do much. Often we'd like to have a more useful
class to manipulate Python objects. But we have already seen such a class
above, and in the <ulink url="object.html">previous section</ulink>: the aptly
named <literal>object</literal> class and it's derivatives. We've already seen that they
can be constructed from a <literal>handle</literal>. The following examples should further
illustrate this fact:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">((</phrase><phrase role="identifier">
handle</phrase><phrase role="special">&lt;&gt;(</phrase><phrase role="identifier">borrowed</phrase><phrase role="special">(</phrase><ulink url="http://www.python.org/doc/current/api/importing.html#l2h-125">PyImport_AddModule</ulink><phrase role="special">(</phrase><phrase role="string">&quot;__main__&quot;</phrase><phrase role="special">)))));</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special"> =</phrase><phrase role="identifier"> main_module</phrase><phrase role="special">.</phrase><phrase role="identifier">attr</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__dict__&quot;</phrase><phrase role="special">);</phrase><phrase role="identifier">
handle</phrase><phrase role="special">&lt;&gt;</phrase><phrase role="identifier"> ignored</phrase><phrase role="special">((</phrase><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="string">
&quot;result = 5 ** 2&quot;</phrase><phrase role="special">
,</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">Py_file_input</ulink><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()</phrase><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">())</phrase><phrase role="special">
));</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> five_squared</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">main_namespace</phrase><phrase role="special">[</phrase><phrase role="string">&quot;result&quot;</phrase><phrase role="special">]);</phrase>
</literal>
</programlisting>
<para>
Here we create a dictionary object for the <literal><emphasis role="underline">_main</emphasis>_</literal> module's namespace.
Then we assign 5 squared to the result variable and read this variable from
the dictionary. Another way to achieve the same result is to let
<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink> return the result directly with <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink>:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> result</phrase><phrase role="special">((</phrase><phrase role="identifier">handle</phrase><phrase role="special">&lt;&gt;(</phrase>
&nbsp;&nbsp;&nbsp;&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="string">&quot;5 ** 2&quot;</phrase><phrase role="special">
,</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()</phrase><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()))</phrase><phrase role="special">
));</phrase><phrase role="keyword">
int</phrase><phrase role="identifier"> five_squared</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">result</phrase><phrase role="special">);</phrase>
</literal>
</programlisting>
<para>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> <emphasis role="bold">Note</emphasis> that <literal>object</literal>'s member function to return the wrapped
<literal>PyObject*</literal> is called <literal>ptr</literal> instead of <literal>get</literal>. This makes sense if you
take into account the different functions that <literal>object</literal> and <literal>handle</literal>
perform.</para>
<anchor id="using_the_interpreter.exception_handling" /><bridgehead renderas="sect2">Exception handling</bridgehead><para>
If an exception occurs in the execution of some Python code, the <ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink>
function returns a null pointer. Constructing a <literal>handle</literal> out of this null
pointer throws <ulink url="../../../v2/errors.html#error_already_set-spec">error_already_set</ulink>,
so basically, the Python exception is automatically translated into a
C++ exception when using <literal>handle</literal>:</para>
<programlisting>
<literal>
<phrase role="keyword">try</phrase><phrase role="special">
{</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> result</phrase><phrase role="special">((</phrase><phrase role="identifier">handle</phrase><phrase role="special">&lt;&gt;(</phrase><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="string">
&quot;5/0&quot;</phrase><phrase role="special">
,</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()</phrase><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()))</phrase><phrase role="special">
));</phrase><phrase role="comment">
// execution will never get here:
</phrase><phrase role="keyword"> int</phrase><phrase role="identifier"> five_divided_by_zero</phrase><phrase role="special"> =</phrase><phrase role="identifier"> extract</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">result</phrase><phrase role="special">);</phrase><phrase role="special">
}</phrase><phrase role="keyword">
catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_already_set</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
// handle the exception in some way
</phrase><phrase role="special">}</phrase>
</literal>
</programlisting>
<para>
The <literal>error_already_set</literal> exception class doesn't carry any information in itself.
To find out more about the Python exception that occurred, you need to use the
<ulink url="http://www.python.org/doc/api/exceptionHandling.html">exception handling functions</ulink>
of the Python/C API in your catch-statement. This can be as simple as calling
<ulink url="http://www.python.org/doc/api/exceptionHandling.html#l2h-70">PyErr_Print()</ulink> to
print the exception's traceback to the console, or comparing the type of the
exception with those of the <ulink url="http://www.python.org/doc/api/standardExceptions.html
standard">exceptions</ulink>:</para>
<programlisting>
<literal>
<phrase role="keyword">catch</phrase><phrase role="special">(</phrase><phrase role="identifier">error_already_set</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (</phrase><phrase role="identifier">PyErr_ExceptionMatches</phrase><phrase role="special">(</phrase><phrase role="identifier">PyExc_ZeroDivisionError</phrase><phrase role="special">))</phrase><phrase role="special">
{</phrase><phrase role="comment">
// handle ZeroDivisionError specially
</phrase><phrase role="special"> }</phrase><phrase role="keyword">
else</phrase><phrase role="special">
{</phrase><phrase role="comment">
// print all other errors to stderr
</phrase><phrase role="identifier"> PyErr_Print</phrase><phrase role="special">();</phrase><phrase role="special">
}</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
(To retrieve even more information from the exception you can use some of the other
exception handling functions listed <ulink url="http://www.python.org/doc/api/exceptionHandling.html">here</ulink>.)</para>
<para>
If you'd rather not have <literal>handle</literal> throw a C++ exception when it is constructed, you
can use the <ulink url="../../../v2/handle.html#allow_null-spec">allow_null</ulink> function in the same
way you'd use borrowed:</para>
<programlisting>
<literal>
<phrase role="identifier">handle</phrase><phrase role="special">&lt;&gt;</phrase><phrase role="identifier"> result</phrase><phrase role="special">((</phrase><phrase role="identifier">allow_null</phrase><phrase role="special">(</phrase><ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">PyRun_String</ulink><phrase role="special">(</phrase><phrase role="string">
&quot;5/0&quot;</phrase><phrase role="special">
,</phrase>&nbsp;<ulink url="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">Py_eval_input</ulink><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()</phrase><phrase role="special">
,</phrase><phrase role="identifier"> main_namespace</phrase><phrase role="special">.</phrase><phrase role="identifier">ptr</phrase><phrase role="special">()))));</phrase><phrase role="keyword">
if</phrase><phrase role="special"> (!</phrase><phrase role="identifier">result</phrase><phrase role="special">)</phrase><phrase role="comment">
// Python exception occurred
</phrase><phrase role="keyword">else</phrase><phrase role="comment">
// everything went okay, it's safe to use the result
</phrase></literal>
</programlisting>
</section></section>
<section id="python.iterators">
<title>Iterators</title>
<para>
In C++, and STL in particular, we see iterators everywhere. Python also has
iterators, but these are two very different beasts.</para>
<para>
<emphasis role="bold">C++ iterators:</emphasis></para>
<itemizedlist>
<listitem>
C++ has 5 type categories (random-access, bidirectional, forward, input, output)
</listitem><listitem>
There are 2 Operation categories: reposition, access
</listitem><listitem>
A pair of iterators is needed to represent a (first/last) range.
</listitem>
</itemizedlist><para>
<emphasis role="bold">Python Iterators:</emphasis></para>
<itemizedlist>
<listitem>
1 category (forward)
</listitem><listitem>
1 operation category (next())
</listitem><listitem>
Raises StopIteration exception at end
</listitem>
</itemizedlist><para>
The typical Python iteration protocol: <literal><emphasis role="bold">for y in x...</emphasis></literal> is as follows:</para>
<programlisting>
<literal>
<phrase role="identifier">iter</phrase><phrase role="special"> =</phrase><phrase role="identifier"> x</phrase><phrase role="special">.</phrase><phrase role="identifier">__iter__</phrase><phrase role="special">()</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> get</phrase><phrase role="identifier"> iterator</phrase><phrase role="keyword">
try</phrase><phrase role="special">:</phrase><phrase role="keyword">
while</phrase><phrase role="number"> 1</phrase><phrase role="special">:</phrase><phrase role="identifier">
y</phrase><phrase role="special"> =</phrase><phrase role="identifier"> iter</phrase><phrase role="special">.</phrase><phrase role="identifier">next</phrase><phrase role="special">()</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> get</phrase><phrase role="identifier"> each</phrase><phrase role="identifier"> item</phrase><phrase role="special">
...</phrase>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<phrase role="identifier"> process</phrase><phrase role="identifier"> y</phrase><phrase role="identifier">
except</phrase><phrase role="identifier"> StopIteration</phrase><phrase role="special">:</phrase><phrase role="identifier"> pass</phrase>&nbsp;&nbsp;#<phrase role="identifier"> iterator</phrase><phrase role="identifier"> exhausted</phrase>
</literal>
</programlisting>
<para>
Boost.Python provides some mechanisms to make C++ iterators play along
nicely as Python iterators. What we need to do is to produce
appropriate <emphasis role="underline">_iter</emphasis>_ function from C++ iterators that is compatible
with the Python iteration protocol. For example:</para>
<programlisting>
<literal>
<phrase role="identifier">object</phrase><phrase role="identifier"> get_iterator</phrase><phrase role="special"> =</phrase><phrase role="identifier"> iterator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special"> &gt;();</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> iter</phrase><phrase role="special"> =</phrase><phrase role="identifier"> get_iterator</phrase><phrase role="special">(</phrase><phrase role="identifier">v</phrase><phrase role="special">);</phrase><phrase role="identifier">
object</phrase><phrase role="identifier"> first</phrase><phrase role="special"> =</phrase><phrase role="identifier"> iter</phrase><phrase role="special">.</phrase><phrase role="identifier">next</phrase><phrase role="special">();</phrase>
</literal>
</programlisting>
<para>
Or for use in class_&lt;&gt;:</para>
<programlisting>
<literal>
<phrase role="special">.</phrase><phrase role="identifier">def</phrase><phrase role="special">(</phrase><phrase role="string">&quot;__iter__&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> iterator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special"> &gt;())</phrase>
</literal>
</programlisting>
<para>
<emphasis role="bold">range</emphasis></para>
<para>
We can create a Python savvy iterator using the range function:</para>
<itemizedlist>
<listitem>
range(start, finish)
</listitem><listitem>
range&lt;Policies,Target&gt;(start, finish)
</listitem>
</itemizedlist><para>
Here, start/finish may be one of:</para>
<itemizedlist>
<listitem>
member data pointers
</listitem><listitem>
member function pointers
</listitem><listitem>
adaptable function object (use Target parameter)
</listitem>
</itemizedlist><para>
<emphasis role="bold">iterator</emphasis></para>
<itemizedlist>
<listitem>
iterator&lt;T, Policies&gt;()
</listitem>
</itemizedlist><para>
Given a container <literal>T</literal>, iterator is a shortcut that simply calls <literal>range</literal>
with &amp;T::begin, &amp;T::end.</para>
<para>
Let's put this into action... Here's an example from some hypothetical
bogon Particle accelerator code:</para>
<programlisting>
<literal>
<phrase role="identifier">f</phrase><phrase role="special"> =</phrase><phrase role="identifier"> Field</phrase><phrase role="special">()</phrase><phrase role="keyword">
for</phrase><phrase role="identifier"> x</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> f</phrase><phrase role="special">.</phrase><phrase role="identifier">pions</phrase><phrase role="special">:</phrase><phrase role="identifier">
smash</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">)</phrase><phrase role="keyword">
for</phrase><phrase role="identifier"> y</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> f</phrase><phrase role="special">.</phrase><phrase role="identifier">bogons</phrase><phrase role="special">:</phrase><phrase role="identifier">
count</phrase><phrase role="special">(</phrase><phrase role="identifier">y</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
Now, our C++ Wrapper:</para>
<programlisting>
<literal>
<phrase role="identifier">class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;Field&quot;</phrase><phrase role="special">)</phrase><phrase role="special">
.</phrase><phrase role="identifier">property</phrase><phrase role="special">(</phrase><phrase role="string">&quot;pions&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> range</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">F</phrase><phrase role="special">::</phrase><phrase role="identifier">p_begin</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">F</phrase><phrase role="special">::</phrase><phrase role="identifier">p_end</phrase><phrase role="special">))</phrase><phrase role="special">
.</phrase><phrase role="identifier">property</phrase><phrase role="special">(</phrase><phrase role="string">&quot;bogons&quot;</phrase><phrase role="special">,</phrase><phrase role="identifier"> range</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">F</phrase><phrase role="special">::</phrase><phrase role="identifier">b_begin</phrase><phrase role="special">,</phrase><phrase role="special"> &amp;</phrase><phrase role="identifier">F</phrase><phrase role="special">::</phrase><phrase role="identifier">b_end</phrase><phrase role="special">));</phrase>
</literal>
</programlisting>
</section>
<section id="python.exception">
<title> Exception Translation</title>
<para>
All C++ exceptions must be caught at the boundary with Python code. This
boundary is the point where C++ meets Python. Boost.Python provides a
default exception handler that translates selected standard exceptions,
then gives up:</para>
<programlisting>
<literal>
<phrase role="identifier">raise</phrase><phrase role="identifier"> RuntimeError</phrase><phrase role="special">,</phrase><phrase role="char"> 'unidentifiable C++ Exception'</phrase>
</literal>
</programlisting>
<para>
Users may provide custom translation. Here's an example:</para>
<programlisting>
<literal>
<phrase role="keyword">struct</phrase><phrase role="identifier"> PodBayDoorException</phrase><phrase role="special">;</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> translator</phrase><phrase role="special">(</phrase><phrase role="identifier">PodBayDoorException</phrase><phrase role="keyword"> const</phrase><phrase role="special">&amp;</phrase><phrase role="identifier"> x</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="identifier">
PyErr_SetString</phrase><phrase role="special">(</phrase><phrase role="identifier">PyExc_UserWarning</phrase><phrase role="special">,</phrase><phrase role="string"> &quot;I'm sorry Dave...&quot;</phrase><phrase role="special">);</phrase><phrase role="special">
}</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">kubrick</phrase><phrase role="special">)</phrase><phrase role="special"> {</phrase><phrase role="identifier">
register_exception_translator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">
PodBayDoorException</phrase><phrase role="special">&gt;(</phrase><phrase role="identifier">translator</phrase><phrase role="special">);</phrase><phrase role="special">
...</phrase>
</literal>
</programlisting>
</section>
<section id="python.techniques">
<title> General Techniques</title>
<para>
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</para>
<section id="python.creating_packages">
<title>Creating Packages</title>
<para>
A Python package is a collection of modules that provide to the user a certain
functionality. If you're not familiar on how to create packages, a good
introduction to them is provided in the
<ulink url="http://www.python.org/doc/current/tut/node8.html">Python Tutorial</ulink>.</para>
<para>
But we are wrapping C++ code, using Boost.Python. How can we provide a nice
package interface to our users? To better explain some concepts, let's work
with an example.</para>
<para>
We have a C++ library that works with sounds: reading and writing various
formats, applying filters to the sound data, etc. It is named (conveniently)
<literal>sounds</literal>. Our library already has a neat C++ namespace hierarchy, like so:</para>
<programlisting>
<literal>
<phrase role="identifier">sounds</phrase><phrase role="special">::</phrase><phrase role="identifier">core</phrase><phrase role="identifier">
sounds</phrase><phrase role="special">::</phrase><phrase role="identifier">io</phrase><phrase role="identifier">
sounds</phrase><phrase role="special">::</phrase><phrase role="identifier">filters</phrase>
</literal>
</programlisting>
<para>
We would like to present this same hierarchy to the Python user, allowing him
to write code like this:</para>
<programlisting>
<literal>
<phrase role="identifier">import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="identifier">
sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">.</phrase><phrase role="identifier">echo</phrase><phrase role="special">(...)</phrase>&nbsp;#<phrase role="identifier"> echo</phrase><phrase role="identifier"> is</phrase><phrase role="identifier"> a</phrase><phrase role="identifier"> C</phrase><phrase role="special">++</phrase><phrase role="identifier"> function</phrase>
</literal>
</programlisting>
<para>
The first step is to write the wrapping code. We have to export each module
separately with Boost.Python, like this:</para>
<programlisting>
<literal>
<phrase role="comment">/* file core.cpp */</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">core</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/* export everything in the sounds::core namespace */</phrase><phrase role="special">
...</phrase><phrase role="special">
}</phrase><phrase role="comment">
/* file io.cpp */</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">io</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/* export everything in the sounds::io namespace */</phrase><phrase role="special">
...</phrase><phrase role="special">
}</phrase><phrase role="comment">
/* file filters.cpp */</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">filters</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="comment">
/* export everything in the sounds::filters namespace */</phrase><phrase role="special">
...</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Compiling these files will generate the following Python extensions:
<literal>core.pyd</literal>, <literal>io.pyd</literal> and <literal>filters.pyd</literal>.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> The extension <literal>.pyd</literal> is used for python extension modules, which
are just shared libraries. Using the default for your system, like <literal>.so</literal> for
Unix and <literal>.dll</literal> for Windows, works just as well.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
Now, we create this directory structure for our Python package:</para>
<programlisting><literal> sounds/
<emphasis role="underline">_init</emphasis>_.py
core.pyd
filters.pyd
io.pyd
</literal></programlisting><para>
The file <literal><emphasis role="underline">_init</emphasis>_.py</literal> is what tells Python that the directory <literal>sounds/</literal> is
actually a Python package. It can be a empty file, but can also perform some
magic, that will be shown later.</para>
<para>
Now our package is ready. All the user has to do is put <literal>sounds</literal> into his
<ulink url="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000">PYTHONPATH</ulink>
and fire up the interpreter:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">io</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> sound</phrase><phrase role="special"> =</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">io</phrase><phrase role="special">.</phrase><phrase role="identifier">open</phrase><phrase role="special">(</phrase><phrase role="char">'file.mp3'</phrase><phrase role="special">)</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> new_sound</phrase><phrase role="special"> =</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">.</phrase><phrase role="identifier">echo</phrase><phrase role="special">(</phrase><phrase role="identifier">sound</phrase><phrase role="special">,</phrase><phrase role="number"> 1.0</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
Nice heh?</para>
<para>
This is the simplest way to create hierarchies of packages, but it is not very
flexible. What if we want to add a <emphasis>pure</emphasis> Python function to the filters
package, for instance, one that applies 3 filters in a sound object at once?
Sure, you can do this in C++ and export it, but why not do so in Python? You
don't have to recompile the extension modules, plus it will be easier to write
it.</para>
<para>
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:</para>
<programlisting>
<literal>
<phrase role="comment">/* file core.cpp */</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">_core</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="special">
...</phrase><phrase role="comment">
/* export everything in the sounds::core namespace */</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Note that we added an underscore to the module name. The filename will have to
be changed to <literal>_core.pyd</literal> as well, and we do the same to the other extension modules.
Now, we change our package hierarchy like so:</para>
<programlisting><literal> sounds/
<emphasis role="underline">_init</emphasis>_.py
core/
<emphasis role="underline">_init</emphasis>_.py
_core.pyd
filters/
<emphasis role="underline">_init</emphasis>_.py
_filters.pyd
io/
<emphasis role="underline">_init</emphasis>_.py
_io.pyd
</literal></programlisting><para>
Note that we created a directory for each extension module, and added a
<emphasis role="underline">_init</emphasis>_.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:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">core</phrase><phrase role="special">.</phrase><phrase role="identifier">_core</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">core</phrase><phrase role="special">.</phrase><phrase role="identifier">_core</phrase><phrase role="special">.</phrase><phrase role="identifier">foo</phrase><phrase role="special">(...)</phrase>
</literal>
</programlisting>
<para>
which is not what we want. But here enters the <literal><emphasis role="underline">_init</emphasis>_.py</literal> magic: everything
that is brought to the <literal><emphasis role="underline">_init</emphasis>_.py</literal> namespace can be accessed directly by the
user. So, all we have to do is bring the entire namespace from <literal>_core.pyd</literal>
to <literal>core/<emphasis role="underline">_init</emphasis><emphasis role="underline">.py]. So add this line of code to [^sounds/core/</emphasis><emphasis role="underline">init</emphasis>_.py</literal>:</para>
<programlisting>
<literal>
<phrase role="identifier">from</phrase><phrase role="identifier"> _core</phrase><phrase role="identifier"> import</phrase><phrase role="special"> *</phrase>
</literal>
</programlisting>
<para>
We do the same for the other packages. Now the user accesses the functions and
classes in the extension modules like before:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">.</phrase><phrase role="identifier">echo</phrase><phrase role="special">(...)</phrase>
</literal>
</programlisting>
<para>
with the additional benefit that we can easily add pure Python functions to
any module, in a way that the user can't tell the difference between a C++
function and a Python function. Let's add a <emphasis>pure</emphasis> Python function,
<literal>echo_noise</literal>, to the <literal>filters</literal> package. This function applies both the
<literal>echo</literal> and <literal>noise</literal> filters in sequence in the given <literal>sound</literal> object. We
create a file named <literal>sounds/filters/echo_noise.py</literal> and code our function:</para>
<programlisting>
<literal>
<phrase role="identifier">import</phrase><phrase role="identifier"> _filters</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> echo_noise</phrase><phrase role="special">(</phrase><phrase role="identifier">sound</phrase><phrase role="special">):</phrase><phrase role="identifier">
s</phrase><phrase role="special"> =</phrase><phrase role="identifier"> _filters</phrase><phrase role="special">.</phrase><phrase role="identifier">echo</phrase><phrase role="special">(</phrase><phrase role="identifier">sound</phrase><phrase role="special">)</phrase><phrase role="identifier">
s</phrase><phrase role="special"> =</phrase><phrase role="identifier"> _filters</phrase><phrase role="special">.</phrase><phrase role="identifier">noise</phrase><phrase role="special">(</phrase><phrase role="identifier">sound</phrase><phrase role="special">)</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> s</phrase>
</literal>
</programlisting>
<para>
Next, we add this line to <literal>sounds<emphasis>filters</emphasis><emphasis role="underline">_init</emphasis>_.py</literal>:</para>
<programlisting>
<literal>
<phrase role="identifier">from</phrase><phrase role="identifier"> echo_noise</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> echo_noise</phrase>
</literal>
</programlisting>
<para>
And that's it. The user now accesses this function like any other function
from the <literal>filters</literal> package:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> import</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> sounds</phrase><phrase role="special">.</phrase><phrase role="identifier">filters</phrase><phrase role="special">.</phrase><phrase role="identifier">echo_noise</phrase><phrase role="special">(...)</phrase>
</literal>
</programlisting>
</section>
<section id="python.extending_wrapped_objects_in_python">
<title>Extending Wrapped Objects in Python</title>
<para>
Thanks to Python's flexibility, you can easily add new methods to a class,
even after it was already created:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="keyword"> class</phrase><phrase role="identifier"> C</phrase><phrase role="special">(</phrase><phrase role="identifier">object</phrase><phrase role="special">):</phrase><phrase role="identifier"> pass</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="special">
&gt;&gt;&gt;</phrase>&nbsp;#<phrase role="identifier"> a</phrase><phrase role="identifier"> regular</phrase><phrase role="identifier"> function</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> def</phrase><phrase role="identifier"> C_str</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="keyword"> return</phrase><phrase role="char"> 'A C instance!'</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="special">
&gt;&gt;&gt;</phrase>&nbsp;#<phrase role="identifier"> now</phrase><phrase role="identifier"> we</phrase><phrase role="identifier"> turn</phrase><phrase role="identifier"> it</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> a</phrase><phrase role="identifier"> member</phrase><phrase role="identifier"> function</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> C</phrase><phrase role="special">.</phrase><phrase role="identifier">__str__</phrase><phrase role="special"> =</phrase><phrase role="identifier"> C_str</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> c</phrase><phrase role="special"> =</phrase><phrase role="identifier"> C</phrase><phrase role="special">()</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> print</phrase><phrase role="identifier"> c</phrase><phrase role="identifier">
A</phrase><phrase role="identifier"> C</phrase><phrase role="identifier"> instance</phrase><phrase role="special">!</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> C_str</phrase><phrase role="special">(</phrase><phrase role="identifier">c</phrase><phrase role="special">)</phrase><phrase role="identifier">
A</phrase><phrase role="identifier"> C</phrase><phrase role="identifier"> instance</phrase><phrase role="special">!</phrase>
</literal>
</programlisting>
<para>
Yes, Python rox. <inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject></inlinemediaobject></para>
<para>
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <literal>point</literal> in C++:</para>
<programlisting>
<literal>
<phrase role="keyword">class</phrase><phrase role="identifier"> point</phrase><phrase role="special"> {...};</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">_geom</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">point</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;point&quot;</phrase><phrase role="special">)...;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
If we are using the technique from the previous session,
<link linkend="python.creating_packages">Creating Packages</link>, we can code directly
into <literal>geom/<emphasis role="underline">_init</emphasis>_.py</literal>:</para>
<programlisting>
<literal>
<phrase role="identifier">from</phrase><phrase role="identifier"> _geom</phrase><phrase role="identifier"> import</phrase><phrase role="special"> *</phrase>
#<phrase role="identifier"> a</phrase><phrase role="identifier"> regular</phrase><phrase role="identifier"> function</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> point_str</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> str</phrase><phrase role="special">((</phrase><phrase role="identifier">self</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">,</phrase><phrase role="identifier"> self</phrase><phrase role="special">.</phrase><phrase role="identifier">y</phrase><phrase role="special">))</phrase>
#<phrase role="identifier"> now</phrase><phrase role="identifier"> we</phrase><phrase role="identifier"> turn</phrase><phrase role="identifier"> it</phrase><phrase role="identifier"> into</phrase><phrase role="identifier"> a</phrase><phrase role="identifier"> member</phrase><phrase role="identifier"> function</phrase><phrase role="identifier">
point</phrase><phrase role="special">.</phrase><phrase role="identifier">__str__</phrase><phrase role="special"> =</phrase><phrase role="identifier"> point_str</phrase>
</literal>
</programlisting>
<para>
<emphasis role="bold">All</emphasis> point instances created from C++ will also have this member function!
This technique has several advantages:</para>
<itemizedlist>
<listitem>
Cut down compile times to zero for these additional functions
</listitem><listitem>
Reduce the memory footprint to virtually zero
</listitem><listitem>
Minimize the need to recompile
</listitem><listitem>
Rapid prototyping (you can move the code to C++ if required without changing the interface)
</listitem>
</itemizedlist><para>
You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that &quot;injects&quot; methods in other classes.</para>
<programlisting>
<literal>
#<phrase role="identifier"> The</phrase><phrase role="identifier"> one</phrase><phrase role="identifier"> Boost</phrase><phrase role="special">.</phrase><phrase role="identifier">Python</phrase><phrase role="identifier"> uses</phrase><phrase role="keyword"> for</phrase><phrase role="identifier"> all</phrase><phrase role="identifier"> wrapped</phrase><phrase role="identifier"> classes</phrase><phrase role="special">.</phrase>
#<phrase role="identifier"> You</phrase><phrase role="identifier"> can</phrase><phrase role="identifier"> use</phrase><phrase role="identifier"> here</phrase><phrase role="identifier"> any</phrase><phrase role="keyword"> class</phrase><phrase role="identifier"> exported</phrase><phrase role="identifier"> by</phrase><phrase role="identifier"> Boost</phrase><phrase role="identifier"> instead</phrase><phrase role="identifier"> of</phrase><phrase role="string"> &quot;point&quot;</phrase><phrase role="identifier">
BoostPythonMetaclass</phrase><phrase role="special"> =</phrase><phrase role="identifier"> point</phrase><phrase role="special">.</phrase><phrase role="identifier">__class__</phrase><phrase role="keyword">
class</phrase><phrase role="identifier"> injector</phrase><phrase role="special">(</phrase><phrase role="identifier">object</phrase><phrase role="special">):</phrase><phrase role="keyword">
class</phrase><phrase role="identifier"> __metaclass__</phrase><phrase role="special">(</phrase><phrase role="identifier">BoostPythonMetaclass</phrase><phrase role="special">):</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> __init__</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="identifier"> name</phrase><phrase role="special">,</phrase><phrase role="identifier"> bases</phrase><phrase role="special">,</phrase><phrase role="identifier"> dict</phrase><phrase role="special">):</phrase><phrase role="keyword">
for</phrase><phrase role="identifier"> b</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> bases</phrase><phrase role="special">:</phrase><phrase role="keyword">
if</phrase><phrase role="identifier"> type</phrase><phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">)</phrase><phrase role="keyword"> not</phrase><phrase role="identifier"> in</phrase><phrase role="special"> (</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="identifier"> type</phrase><phrase role="special">):</phrase><phrase role="keyword">
for</phrase><phrase role="identifier"> k</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> dict</phrase><phrase role="special">.</phrase><phrase role="identifier">items</phrase><phrase role="special">():</phrase><phrase role="identifier">
setattr</phrase><phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">,</phrase><phrase role="identifier">k</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="special">)</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> type</phrase><phrase role="special">.</phrase><phrase role="identifier">__init__</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">,</phrase><phrase role="identifier"> name</phrase><phrase role="special">,</phrase><phrase role="identifier"> bases</phrase><phrase role="special">,</phrase><phrase role="identifier"> dict</phrase><phrase role="special">)</phrase>
#<phrase role="identifier"> inject</phrase><phrase role="identifier"> some</phrase><phrase role="identifier"> methods</phrase><phrase role="identifier"> in</phrase><phrase role="identifier"> the</phrase><phrase role="identifier"> point</phrase><phrase role="identifier"> foo</phrase><phrase role="keyword">
class</phrase><phrase role="identifier"> more_point</phrase><phrase role="special">(</phrase><phrase role="identifier">injector</phrase><phrase role="special">,</phrase><phrase role="identifier"> point</phrase><phrase role="special">):</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> __repr__</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="keyword">
return</phrase><phrase role="char"> 'Point(x=%s, y=%s)'</phrase><phrase role="special"> %</phrase><phrase role="special"> (</phrase><phrase role="identifier">self</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">,</phrase><phrase role="identifier"> self</phrase><phrase role="special">.</phrase><phrase role="identifier">y</phrase><phrase role="special">)</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> foo</phrase><phrase role="special">(</phrase><phrase role="identifier">self</phrase><phrase role="special">):</phrase><phrase role="identifier">
print</phrase><phrase role="char"> 'foo!'</phrase>
</literal>
</programlisting>
<para>
Now let's see how it got:</para>
<programlisting>
<literal>
<phrase role="special">&gt;&gt;&gt;</phrase><phrase role="identifier"> print</phrase><phrase role="identifier"> point</phrase><phrase role="special">()</phrase><phrase role="identifier">
Point</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">=</phrase><phrase role="number">10</phrase><phrase role="special">,</phrase><phrase role="identifier"> y</phrase><phrase role="special">=</phrase><phrase role="number">10</phrase><phrase role="special">)</phrase><phrase role="special">
&gt;&gt;&gt;</phrase><phrase role="identifier"> point</phrase><phrase role="special">().</phrase><phrase role="identifier">foo</phrase><phrase role="special">()</phrase><phrase role="identifier">
foo</phrase><phrase role="special">!</phrase>
</literal>
</programlisting>
<para>
Another useful idea is to replace constructors with factory functions:</para>
<programlisting>
<literal>
<phrase role="identifier">_point</phrase><phrase role="special"> =</phrase><phrase role="identifier"> point</phrase><phrase role="identifier">
def</phrase><phrase role="identifier"> point</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">,</phrase><phrase role="identifier"> y</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">):</phrase><phrase role="keyword">
return</phrase><phrase role="identifier"> _point</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">,</phrase><phrase role="identifier"> y</phrase><phrase role="special">)</phrase>
</literal>
</programlisting>
<para>
In this simple case there is not much gained, but for constructurs with
many overloads and/or arguments this is often a great simplification, again
with virtually zero memory footprint and zero compile-time overhead for
the keyword support.</para>
</section>
<section id="python.reducing_compiling_time">
<title>Reducing Compiling Time</title>
<para>
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:</para>
<programlisting>
<literal>
<phrase role="comment">/* file point.cpp */</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">point</phrase><phrase role="special">.</phrase><phrase role="identifier">h</phrase><phrase role="special">&gt;</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> export_point</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">point</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;point&quot;</phrase><phrase role="special">)...;</phrase><phrase role="special">
}</phrase><phrase role="comment">
/* file triangle.cpp */</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">triangle</phrase><phrase role="special">.</phrase><phrase role="identifier">h</phrase><phrase role="special">&gt;</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> export_triangle</phrase><phrase role="special">()</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">triangle</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;triangle&quot;</phrase><phrase role="special">)...;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Now you create a file <literal>main.cpp</literal>, which contains the <literal>BOOST_PYTHON_MODULE</literal>
macro, and call the various export functions inside it.</para>
<programlisting>
<literal>
<phrase role="keyword">void</phrase><phrase role="identifier"> export_point</phrase><phrase role="special">();</phrase><phrase role="keyword">
void</phrase><phrase role="identifier"> export_triangle</phrase><phrase role="special">();</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">_geom</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
export_point</phrase><phrase role="special">();</phrase><phrase role="identifier">
export_triangle</phrase><phrase role="special">();</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
Compiling and linking together all this files produces the same result as the
usual approach:</para>
<programlisting>
<literal>
<phrase role="preprocessor">#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">python</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">point</phrase><phrase role="special">.</phrase><phrase role="identifier">h</phrase><phrase role="special">&gt;</phrase><phrase role="preprocessor">
#include</phrase><phrase role="special"> &lt;</phrase><phrase role="identifier">triangle</phrase><phrase role="special">.</phrase><phrase role="identifier">h</phrase><phrase role="special">&gt;</phrase><phrase role="identifier">
BOOST_PYTHON_MODULE</phrase><phrase role="special">(</phrase><phrase role="identifier">_geom</phrase><phrase role="special">)</phrase><phrase role="special">
{</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">point</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;point&quot;</phrase><phrase role="special">)...;</phrase><phrase role="identifier">
class_</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">triangle</phrase><phrase role="special">&gt;(</phrase><phrase role="string">&quot;triangle&quot;</phrase><phrase role="special">)...;</phrase><phrase role="special">
}</phrase>
</literal>
</programlisting>
<para>
but the memory is kept under control.</para>
<para>
This method is recommended too if you are developing the C++ library and
exporting it to Python at the same time: changes in a class will only demand
the compilation of a single cpp, instead of the entire wrapper code.</para>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> If you're exporting your classes with <ulink url="../../../../pyste/index.html">Pyste</ulink>,
take a look at the <literal>--multiple</literal> option, that generates the wrappers in
various files as demonstrated here.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<informaltable frame="all">
<?dbhtml table-width="74%" ?>
<tgroup cols="1">
<tbody>
<row>
<entry>
<inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject></inlinemediaobject> This method is useful too if you are getting the error message
<emphasis>&quot;fatal error C1204:Compiler limit:internal structure overflow&quot;</emphasis> when compiling
a large source file, as explained in the <ulink url="../../../v2/faq.html#c1204">FAQ</ulink>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section></section>
</library>