2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-21 17:12:22 +00:00

This commit was manufactured by cvs2svn to create branch 'boost'.

[SVN r1472]
This commit is contained in:
nobody
2003-09-03 20:47:14 +00:00
parent b7ae3540e2
commit 650560a094
45 changed files with 0 additions and 4399 deletions

View File

@@ -1,77 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Basic Interface</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="object_interface.html">
<link rel="next" href="derived_object_types.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Basic Interface</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="object_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="derived_object_types.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Class <tt>object</tt> wraps <tt>PyObject*</tt>. All the intricacies of dealing with
<tt>PyObject</tt>s such as managing reference counting are handled by the
<tt>object</tt> class. C++ object interoperability is seamless. Boost.Python C++
<tt>object</tt>s can in fact be explicitly constructed from any C++ object.</p>
<p>
To illustrate, this Python code snippet:</p>
<code><pre>
<span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>, </span><span class=identifier>y</span><span class=special>):
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>y </span><span class=special>== </span><span class=literal>'foo'</span><span class=special>):
</span><span class=identifier>x</span><span class=special>[</span><span class=number>3</span><span class=special>:</span><span class=number>7</span><span class=special>] </span><span class=special>= </span><span class=literal>'bar'
</span><span class=keyword>else</span><span class=special>:
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>items </span><span class=special>+= </span><span class=identifier>y</span><span class=special>(</span><span class=number>3</span><span class=special>, </span><span class=identifier>x</span><span class=special>)
</span><span class=keyword>return </span><span class=identifier>x
</span><span class=identifier>def </span><span class=identifier>getfunc</span><span class=special>():
</span><span class=keyword>return </span><span class=identifier>f</span><span class=special>;
</span></pre></code>
<p>
Can be rewritten in C++ using Boost.Python facilities this way:</p>
<code><pre>
<span class=identifier>object </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>object </span><span class=identifier>x</span><span class=special>, </span><span class=identifier>object </span><span class=identifier>y</span><span class=special>) </span><span class=special>{
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>y </span><span class=special>== </span><span class=string>&quot;foo&quot;</span><span class=special>)
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>slice</span><span class=special>(</span><span class=number>3</span><span class=special>,</span><span class=number>7</span><span class=special>) </span><span class=special>= </span><span class=string>&quot;bar&quot;</span><span class=special>;
</span><span class=keyword>else
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;items&quot;</span><span class=special>) </span><span class=special>+= </span><span class=identifier>y</span><span class=special>(</span><span class=number>3</span><span class=special>, </span><span class=identifier>x</span><span class=special>);
</span><span class=keyword>return </span><span class=identifier>x</span><span class=special>;
</span><span class=special>}
</span><span class=identifier>object </span><span class=identifier>getfunc</span><span class=special>() </span><span class=special>{
</span><span class=keyword>return </span><span class=identifier>object</span><span class=special>(</span><span class=identifier>f</span><span class=special>);
</span><span class=special>}
</span></pre></code>
<p>
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.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="object_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="derived_object_types.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,186 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Building an Extension Module </title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="class_data_members.html">
<link rel="next" href="inheritance.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><strong>Building
an Extension Module</strong></font> </td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr.gif" border="0"></td>
<td width="20"><img src="theme/r_arr.gif" border="0"></td>
</tr>
</table>
<h2>Building Boost.Python</h2>
<p>Every Boost.Python extension module must be linked with the boost_python shared
library. To build boost_python, use <a href="file:///C:/dev/boost/tools/build/index.html">Boost.Build</a>
in the usual way from the <tt>libs/python/build</tt> subdirectory of your boost
installation (if you have already built boost from the top level this may have
no effect, since the work is already done).</p>
<h2>Configuration</h2>
<p>You may need to configure the following variables to point Boost.Build at your
Python installation:</p>
<table width="95%" border="0" align="center">
<tr class="table_title">
<td width="24%">Variable Name</td>
<td width="20%">Semantics</td>
<td width="21%">Default</td>
<td width="35%">Notes</td>
</tr>
<tr class="table_cells">
<td><tt>PYTHON_ROOT</tt></td>
<td> The root directory of your Python installation</td>
<td>Windows: <tt><br>
c:/tools/python <br>
Unix: /usr/local</tt></td>
<td>On Unix, this is the <tt>--with-prefix=</tt> directory used to configure
Python</td>
</tr>
<tr class="table_cells">
<td><tt>PYTHON_VERSION</tt></td>
<td> The The 2-part python Major.Minor version number</td>
<td>Windows: 2.1 Unix: 1.5</td>
<td>Be sure not to include a third number, e.g. not &quot;2.2.1&quot;, even
if that's the version you have.</td>
</tr>
<tr class="table_cells">
<td><tt>PYTHON_INCLUDES</tt></td>
<td> path to Python <span class="preprocessor">#include</span> directories</td>
<td>Autoconfigured from <tt><br>
PYTHON_ROOT</tt></td>
<td>&nbsp;</td>
</tr>
<tr class="table_cells">
<td><tt>PYTHON_LIB_PATH</tt></td>
<td>path to Python library object.</td>
<td>Autoconfigured from <tt><br>
PYTHON_ROOT</tt></td>
<td>&nbsp;</td>
</tr>
<tr class="table_cells">
<td><tt>PYTHON_STDLIB_PATH</tt></td>
<td>path to Python standard library modules</td>
<td>Autoconfigured from <tt><br>
PYTHON_ROOT</tt></td>
<td>&nbsp;</td>
</tr>
<tr class="table_cells">
<td height="129"><tt>CYGWIN_ROOT</tt></td>
<td> path to the user's Cygwin installation</td>
<td>Autoconfigured from <tt><br>
PYTHON_ROOT</tt></td>
<td><a href="http://www.cygwin.com">Cygwin</a> only. This and the following
two settings are useful when building with multiple toolsets on Windows,
since Cygwin requires a different build of Python.</td>
</tr>
<tr class="table_cells">
<td height="21"><tt>GCC_PYTHON_ROOT</tt></td>
<td>path to the user's Cygwin Python installation</td>
<td><tt>$(CYGWIN_ROOT)<br>
/usr/local</tt></td>
<td> <a href="http://www.cygwin.com">Cygwin</a> only</td>
</tr>
<tr class="table_cells">
<td><tt>GCC_DEBUG_PYTHON_ROOT</tt></td>
<td> path to the user's Cygwin <a href="#variants">pydebug</a>
build</td>
<td><tt>$(CYGWIN_ROOT)<br>
/usr/local/pydebug</tt></td>
<td> <a href="http://www.cygwin.com">Cygwin</a> only</td>
</tr>
</table>
<h2>Results</h2>
<p>The build process will create a <tt>libs/python/build/bin-stage</tt> subdirectory
of the boost root (or of <tt>$(ALL_LOCATE_TARGET)</tt>, if you have set that
variable), containing the built libraries. The libraries are actually built
to unique directories for each toolset and variant elsewhere in the filesystem,
and copied to the bin-stage directory as a convenience, so if you build with
multiple toolsets at once, the product of later toolsets will overwrite that
of earlier toolsets in bin-stage.</p>
<h2>Testing</h2>
<p>To build and test Boost.Python from within the <tt>libs/python/build directory</tt>,
invoke</p>
<pre> bjam -sTOOLS=<a href="../../../tools/build/index.html">toolset</a> test</pre>
<p>This will update all of the Boost.Python v1 test and example targets. The tests
are relatively quiet by default. To get more-verbose output, you might try</p>
<pre> bjam -sTOOLS=<a href="../../../tools/build/index.html">toolset</a> -sPYTHON_TEST_ARGS=-v test</pre>
<p>which will print each test's Python code with the expected output as it passes.</p>
<h2>Building your Extension Module</h2>
<p>Though there are other approaches, the easiest way to build an extension module
using Boost.Python is with Boost.Build. Until Boost.Build v2 is released, cross-project
build dependencies are not supported, so it works most smoothly if you add a
new subproject to your boost installation. The <tt>libs/python/example</tt>
subdirectory of your boost installation contains a minimal example (along with
many extra sources). To copy the example subproject:</p>
<ol>
<li> Create a new subdirectory in,<tt> libs/python</tt>, say <tt>libs/python/my_project</tt>.</li>
<li> Copy <a href="../example/Jamfile"><tt>libs/python/example/Jamfile</tt></a>
to your new directory.</li>
<li> Edit the Jamfile as appropriate for your project. You'll want to change
the <tt>subproject</tt> rule invocation at the top, and the names of some
of the source files and/or targets.</li>
</ol>
<p>If you can't modify or copy your boost installation, the alternative is to
create your own Boost.Build project. A similar example you can use as a starting
point is available in <a href="../example/project.zip">this archive</a>. You'll
need to edit the Jamfile and Jamrules files, depending on the relative location
of your Boost installation and the new project. Note that automatic testing
of extension modules is not available in this configuration.</p>
<h2>Build Variants</h2>
<p>Three variant configurations of all python-related targets are supported, and
can be selected by setting the BUILD variable:</p>
<p> * <tt>release</tt> (optimization, <tt>-DNDEBUG</tt>)<br>
* <tt>debug</tt> (no optimization <tt>-D_DEBUG</tt>)<br>
* <tt>debug-python</tt> (no optimization, <tt>-D_DEBUG -DBOOST_DEBUG_PYTHON</tt>)</p>
<p>The first two variants of the boost_python library are built by default, and
are compatible with the default Python distribution. The debug-python variant
corresponds to a specially-built debugging version of Python. On Unix platforms,
this python is built by adding <tt>--with-pydebug</tt> when configuring the
Python build. On Windows, the debugging version of Python is generated by the
&quot;Win32 Debug&quot; target of the PCBuild.dsw Visual C++ 6.0 project in
the PCBuild subdirectory of your Python distribution. Extension modules built
with Python debugging enabled are not link-compatible with a non-debug build
of Python. Since few people actually have a debug build of Python (it doesn't
come with the standard distribution), the normal debug variant builds modules
which are compatible with ordinary Python.</p>
<p>On many windows compilers, when extension modules are built with <tt>-D_DEBUG</tt>,
Python defaults to force linking with a special debugging version of the Python
DLL. Since this debug DLL isn't supplied with the default Python installation
for Windows, Boost.Python uses <a href="../../../boost/python/detail/wrap_python.hpp"><tt>boost/python/detail/wrap_python.hpp</tt></a>
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is <span class="preprocessor">#included</span>
- unless <tt>BOOST_DEBUG_PYTHON</tt> is defined.</p>
<p>If you want the extra runtime checks available with the debugging version of
the library, <span class="preprocessor">#define</span> <tt>BOOST_DEBUG_PYTHON</tt>
to re-enable python debuggin, and link with the debug-python variant of boost_python.</p>
<p>If you do not <span class="preprocessor">#define</span> <tt>BOOST_DEBUG_PYTHON</tt>,
be sure that any source files in your extension module <span class="preprocessor">#include</span>
<tt>&lt;boost/python/detail/wrap_python.hpp&gt;</tt> instead of the usual <tt>Python.h</tt>,
or you will have link incompatibilities.</p>
<code></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr.gif" border="0"></td>
<td width="20"><img src="theme/r_arr.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,191 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Building Hello World</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="quickstart.html">
<link rel="next" href="exposing_classes.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Building Hello World</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="quickstart.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exposing_classes.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<a name="from_start_to_finish"></a><h2>From Start To Finish</h2><p>
Now the first thing you'd want to do is to build the Hello World module and
try it for yourself in Python. In this section, we shall outline the steps
necessary to achieve that. We shall use the build tool that comes bundled
with every boost distribution: <b>bjam</b>.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/lens.gif"></img> <b>Building without bjam</b><br><br>
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 <tt>bjam</tt>.
</td>
</tr>
</table>
<p>
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: <a href="../../building.html">
building.html</a>.
After this brief <i>bjam</i> tutorial, we should have built two DLLs:</p>
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
if you are on Windows, and</p>
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
if you are on Unix.</p>
<p>
The tutorial example can be found in the directory:
<tt>libs/python/example/tutorial</tt>. There, you can find:</p>
<ul><li>hello.cpp</li><li>Jamfile</li></ul><p>
The <tt>hello.cpp</tt> file is our C++ hello world example. The <tt>Jamfile</tt> is a
minimalist <i>bjam</i> script that builds the DLLs for us.</p>
<p>
Before anything else, you should have the bjam executable in your boost
directory or somewhere in your path such that <tt>bjam</tt> can be executed in
the command line. Pre-built Boost.Jam executables are available for most
platforms. For example, a pre-built Microsoft Windows bjam executable can
be downloaded <a href="http://boost.sourceforge.net/jam-executables/bin.ntx86/bjam.zip">
here</a>.
The complete list of bjam pre-built
executables can be found <a href="../../../../../tools/build/index.html#Jam">
here</a>.</p>
<a name="lets_jam_"></a><h2>Lets Jam!</h2><p>
<img src="theme/jam.png"></img></p>
<p>
Here is our minimalist Jamfile:</p>
<code><pre>
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
;
</pre></code><p>
First, we need to specify our location in the boost project hierarchy.
It so happens that the tutorial example is located in <tt>/libs/python/example/tutorial</tt>.
Thus:</p>
<code><pre>
subproject libs/python/example/tutorial ;
</pre></code><p>
Then we will include the definitions needed by Python modules:</p>
<code><pre>
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
</pre></code><p>
Finally we declare our <tt>hello</tt> extension:</p>
<code><pre>
extension hello # Declare a Python extension called hello
: hello.cpp # source
&lt;dll&gt;../../build/boost_python # dependencies
;
</pre></code><a name="running_bjam"></a><h2>Running bjam</h2><p>
<i>bjam</i> is run using your operating system's command line interpreter.</p>
<blockquote><p>Start it up.</p></blockquote><p>
Make sure that the environment is set so that we can invoke the C++
compiler. With MSVC, that would mean running the <tt>Vcvars32.bat</tt> batch
file. For instance:</p>
<code><pre>
<span class=identifier>C</span><span class=special>:\</span><span class=identifier>Program </span><span class=identifier>Files</span><span class=special>\</span><span class=identifier>Microsoft </span><span class=identifier>Visual </span><span class=identifier>Studio</span><span class=special>\</span><span class=identifier>VC98</span><span class=special>\</span><span class=identifier>bin</span><span class=special>\</span><span class=identifier>Vcvars32</span><span class=special>.</span><span class=identifier>bat
</span></pre></code>
<p>
Some environment variables will have to be setup for proper building of our
Python modules. Example:</p>
<code><pre>
<span class=identifier>set </span><span class=identifier>PYTHON_ROOT</span><span class=special>=</span><span class=identifier>c</span><span class=special>:/</span><span class=identifier>dev</span><span class=special>/</span><span class=identifier>tools</span><span class=special>/</span><span class=identifier>python
</span><span class=identifier>set </span><span class=identifier>PYTHON_VERSION</span><span class=special>=</span><span class=number>2.2
</span></pre></code>
<p>
The above assumes that the Python installation is in <tt>c:/dev/tools/python</tt>
and that we are using Python version 2.2. You'll have to tweak this path
appropriately. <img src="theme/note.gif"></img> Be sure not to include a third number, e.g. <b>not</b> &quot;2.2.1&quot;,
even if that's the version you have.</p>
<p>
Now we are ready... Be sure to <tt>cd</tt> to <tt>libs/python/example/tutorial</tt>
where the tutorial <tt>&quot;hello.cpp&quot;</tt> and the <tt>&quot;Jamfile&quot;</tt> is situated.</p>
<p>
Finally:</p>
<code><pre>
<span class=identifier>bjam </span><span class=special>-</span><span class=identifier>sTOOLS</span><span class=special>=</span><span class=identifier>msvc
</span></pre></code>
<p>
We are again assuming that we are using Microsoft Visual C++ version 6. If
not, then you will have to specify the appropriate tool. See
<a href="../../../../../tools/build/index.html">
Building Boost Libraries</a> for
further details.</p>
<p>
It should be building now:</p>
<code><pre>
cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc
...patience...
...found 1703 targets...
...updating 40 targets...
</pre></code><p>
And so on... Finally:</p>
<code><pre>
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...
</pre></code><p>
If all is well, you should now have:</p>
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
if you are on Windows, and</p>
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
if you are on Unix.</p>
<p>
<tt>boost_python.dll</tt> can be found somewhere in <tt>libs\python\build\bin</tt>
while <tt>hello.pyd</tt> can be found somewhere in
<tt>libs\python\example\tutorial\bin</tt>. After a successful build, you can just
link in these DLLs with the Python interpreter. In Windows for example, you
can simply put these libraries inside the directory where the Python
executable is.</p>
<p>
You may now fire up Python and run our hello module:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
</span><span class=identifier>hello</span><span class=special>, </span><span class=identifier>world
</span></pre></code>
<blockquote><p><b>There you go... Have fun!</b></p></blockquote><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="quickstart.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exposing_classes.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,169 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Call Policies</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="functions.html">
<link rel="next" href="default_arguments.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Call Policies</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="default_arguments.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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:</p>
<code><pre>
<span class=identifier>X</span><span class=special>&amp; </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>&amp; </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>);
</span></pre></code>
<p>
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</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>) </span>#<span class=identifier>x </span><span class=identifier>refers </span><span class=identifier>to </span><span class=identifier>some </span><span class=identifier>C</span><span class=special>++ </span><span class=identifier>X
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>del </span><span class=identifier>y
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>some_method</span><span class=special>() </span>#<span class=identifier>CRASH</span><span class=special>!
</span></pre></code>
<p>
What's the problem?</p>
<p>
Well, what if f() was implemented as shown below:</p>
<code><pre>
<span class=identifier>X</span><span class=special>&amp; </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>&amp; </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z </span><span class=special>= </span><span class=identifier>z</span><span class=special>;
</span><span class=keyword>return </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>;
</span><span class=special>}
</span></pre></code>
<p>
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.</p>
<p>
Here's what's happening:</p>
<ol><li><tt>f</tt> is called passing in a reference to <tt>y</tt> and a pointer to <tt>z</tt></li><li>A reference to <tt>y.x</tt> is returned</li><li><tt>y</tt> is deleted. <tt>x</tt> is a dangling reference</li><li><tt>x.some_method()</tt> is called</li><li><b>BOOM!</b></li></ol><p>
We could copy result into a new object:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>).</span><span class=identifier>set</span><span class=special>(</span><span class=number>42</span><span class=special>) </span>#<span class=identifier>Result </span><span class=identifier>disappears
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>get</span><span class=special>() </span>#<span class=identifier>No </span><span class=identifier>crash</span><span class=special>, </span><span class=identifier>but </span><span class=identifier>still </span><span class=identifier>bad
</span><span class=number>3.14
</span></pre></code>
<p>
This is not really our intent of our C++ interface. We've broken our
promise that the Python interface should reflect the C++ interface as
closely as possible.</p>
<p>
Our problems do not end there. Suppose Y is implemented as follows:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Y
</span><span class=special>{
</span><span class=identifier>X </span><span class=identifier>x</span><span class=special>; </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>;
</span><span class=keyword>int </span><span class=identifier>z_value</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>z</span><span class=special>-&gt;</span><span class=identifier>value</span><span class=special>(); </span><span class=special>}
</span><span class=special>};
</span></pre></code>
<p>
Notice that the data member <tt>z</tt> is held by class Y using a raw
pointer. Now we have a potential dangling pointer problem inside Y:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>) </span>#<span class=identifier>y </span><span class=identifier>refers </span><span class=identifier>to </span><span class=identifier>z
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>del </span><span class=identifier>z </span>#<span class=identifier>Kill </span><span class=identifier>the </span><span class=identifier>z </span><span class=identifier>object
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z_value</span><span class=special>() </span>#<span class=identifier>CRASH</span><span class=special>!
</span></pre></code>
<p>
For reference, here's the implementation of <tt>f</tt> again:</p>
<code><pre>
<span class=identifier>X</span><span class=special>&amp; </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>&amp; </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z </span><span class=special>= </span><span class=identifier>z</span><span class=special>;
</span><span class=keyword>return </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>;
</span><span class=special>}
</span></pre></code>
<p>
Here's what's happening:</p>
<ol><li><tt>f</tt> is called passing in a reference to <tt>y</tt> and a pointer to <tt>z</tt></li><li>A pointer to <tt>z</tt> is held by <tt>y</tt></li><li>A reference to <tt>y.x</tt> is returned</li><li><tt>z</tt> is deleted. <tt>y.z</tt> is a dangling pointer</li><li><tt>y.z_value()</tt> is called</li><li><tt>z-&gt;value()</tt> is called</li><li><b>BOOM!</b></li></ol><a name="call_policies"></a><h2>Call Policies</h2><p>
Call Policies may be used in situations such as the example detailed above.
In our example, <tt>return_internal_reference</tt> and <tt>with_custodian_and_ward</tt>
are our friends:</p>
<code><pre>
<span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=identifier>f</span><span class=special>,
</span><span class=identifier>return_internal_reference</span><span class=special>&lt;</span><span class=number>1</span><span class=special>,
</span><span class=identifier>with_custodian_and_ward</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>&gt; </span><span class=special>&gt;());
</span></pre></code>
<p>
What are the <tt>1</tt> and <tt>2</tt> parameters, you ask?</p>
<code><pre>
<span class=identifier>return_internal_reference</span><span class=special>&lt;</span><span class=number>1
</span></pre></code>
<p>
Informs Boost.Python that the first argument, in our case <tt>Y&amp; y</tt>, is the
owner of the returned reference: <tt>X&amp;</tt>. The &quot;<tt>1</tt>&quot; simply specifies the
first argument. In short: &quot;return an internal reference <tt>X&amp;</tt> owned by the
1st argument <tt>Y&amp; y</tt>&quot;.</p>
<code><pre>
<span class=identifier>with_custodian_and_ward</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>&gt;
</span></pre></code>
<p>
Informs Boost.Python that the lifetime of the argument indicated by ward
(i.e. the 2nd argument: <tt>Z* z</tt>) is dependent on the lifetime of the
argument indicated by custodian (i.e. the 1st argument: <tt>Y&amp; y</tt>).</p>
<p>
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:</p>
<code><pre>
<span class=identifier>policy1</span><span class=special>&lt;</span><span class=identifier>args</span><span class=special>...,
</span><span class=identifier>policy2</span><span class=special>&lt;</span><span class=identifier>args</span><span class=special>...,
</span><span class=identifier>policy3</span><span class=special>&lt;</span><span class=identifier>args</span><span class=special>...&gt; </span><span class=special>&gt; </span><span class=special>&gt;
</span></pre></code>
<p>
Here is the list of predefined call policies. A complete reference detailing
these can be found <a href="../../v2/reference.html#models_of_call_policies">
here</a>.</p>
<ul><li><b>with_custodian_and_ward</b><br> Ties lifetimes of the arguments</li><li><b>with_custodian_and_ward_postcall</b><br> Ties lifetimes of the arguments and results</li><li><b>return_internal_reference</b><br> Ties lifetime of one argument to that of result</li><li><b>return_value_policy&lt;T&gt; with T one of:</b><br></li><li><b>reference_existing_object</b><br>naïve (dangerous) approach</li><li><b>copy_const_reference</b><br>Boost.Python v1 approach</li><li><b>copy_non_const_reference</b><br></li><li><b>manage_new_object</b><br> Adopt a pointer and hold the instance</li></ul><table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/smiley.gif"></img> <b>Remember the Zen, Luke:</b><br><br>
&quot;Explicit is better than implicit&quot;<br>
&quot;In the face of ambiguity, refuse the temptation to guess&quot;<br> </td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="default_arguments.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,77 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Class Data Members</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="constructors.html">
<link rel="next" href="class_properties.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Class Data Members</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="constructors.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_properties.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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 <b>read-only</b> or
<b>read-write</b>. Consider this class <tt>Var</tt>:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Var
</span><span class=special>{
</span><span class=identifier>Var</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>name</span><span class=special>) </span><span class=special>: </span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>), </span><span class=identifier>value</span><span class=special>() </span><span class=special>{}
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=keyword>const </span><span class=identifier>name</span><span class=special>;
</span><span class=keyword>float </span><span class=identifier>value</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<p>
Our C++ <tt>Var</tt> class and its data members can be exposed to Python:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Var</span><span class=special>&gt;(</span><span class=string>&quot;Var&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>&quot;name&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>name</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def_readwrite</span><span class=special>(</span><span class=string>&quot;value&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>value</span><span class=special>);
</span></pre></code>
<p>
Then, in Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>Var</span><span class=special>(</span><span class=literal>'pi'</span><span class=special>)
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value </span><span class=special>= </span><span class=number>3.14
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>name</span><span class=special>, </span><span class=literal>'is around'</span><span class=special>, </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value
</span><span class=identifier>pi </span><span class=identifier>is </span><span class=identifier>around </span><span class=number>3.14
</span></pre></code>
<p>
Note that <tt>name</tt> is exposed as <b>read-only</b> while <tt>value</tt> is exposed
as <b>read-write</b>.</p>
<code><pre>
&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
</pre></code><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="constructors.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_properties.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,109 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Class Operators/Special Functions</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="class_virtual_functions.html">
<link rel="next" href="functions.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Class Operators/Special Functions</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_virtual_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<a name="python_operators"></a><h2>Python Operators</h2><p>
C is well known for the abundance of operators. C++ extends this to the
extremes by allowing operator overloading. Boost.Python takes advantage of
this and makes it easy to wrap C++ operator-powered classes.</p>
<p>
Consider a file position class <tt>FilePos</tt> and a set of operators that take
on FilePos instances:</p>
<code><pre>
<span class=keyword>class </span><span class=identifier>FilePos </span><span class=special>{ </span><span class=comment>/*...*/ </span><span class=special>};
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>+(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=keyword>int</span><span class=special>);
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>+(</span><span class=keyword>int</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
</span><span class=keyword>int </span><span class=keyword>operator</span><span class=special>-(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>-(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=keyword>int</span><span class=special>);
</span><span class=identifier>FilePos</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>+=(</span><span class=identifier>FilePos</span><span class=special>&amp;, </span><span class=keyword>int</span><span class=special>);
</span><span class=identifier>FilePos</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>-=(</span><span class=identifier>FilePos</span><span class=special>&amp;, </span><span class=keyword>int</span><span class=special>);
</span><span class=keyword>bool </span><span class=keyword>operator</span><span class=special>&lt;(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
</span></pre></code>
<p>
The class and the various operators can be mapped to Python rather easily
and intuitively:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>FilePos</span><span class=special>&gt;(</span><span class=string>&quot;FilePos&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>+ </span><span class=keyword>int</span><span class=special>()) </span><span class=comment>// __add__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=keyword>int</span><span class=special>() </span><span class=special>+ </span><span class=identifier>self</span><span class=special>) </span><span class=comment>// __radd__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>- </span><span class=identifier>self</span><span class=special>) </span><span class=comment>// __sub__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>- </span><span class=keyword>int</span><span class=special>()) </span><span class=comment>// __rsub__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>+= </span><span class=keyword>int</span><span class=special>()) </span><span class=comment>// __iadd__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>-= </span><span class=identifier>other</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>&lt; </span><span class=identifier>self</span><span class=special>); </span><span class=comment>// __lt__
</span></pre></code>
<p>
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 <tt>self</tt> refers to FilePos object. Also, not every class <tt>T</tt> that
you might need to interact with in an operator expression is (cheaply)
default-constructible. You can use <tt>other&lt;T&gt;()</tt> in place of an actual
<tt>T</tt> instance when writing &quot;self expressions&quot;.</p>
<a name="special_methods"></a><h2>Special Methods</h2><p>
Python has a few more <i>Special Methods</i>. 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 <i>special functions</i>. Example:</p>
<code><pre>
<span class=keyword>class </span><span class=identifier>Rational
</span><span class=special>{ </span><span class=keyword>operator </span><span class=keyword>double</span><span class=special>() </span><span class=keyword>const</span><span class=special>; </span><span class=special>};
</span><span class=identifier>Rational </span><span class=identifier>pow</span><span class=special>(</span><span class=identifier>Rational</span><span class=special>, </span><span class=identifier>Rational</span><span class=special>);
</span><span class=identifier>Rational </span><span class=identifier>abs</span><span class=special>(</span><span class=identifier>Rational</span><span class=special>);
</span><span class=identifier>ostream</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>&lt;&lt;(</span><span class=identifier>ostream</span><span class=special>&amp;,</span><span class=identifier>Rational</span><span class=special>);
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Rational</span><span class=special>&gt;()
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>float_</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) </span><span class=comment>// __float__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>pow</span><span class=special>(</span><span class=identifier>self</span><span class=special>, </span><span class=identifier>other</span><span class=special>&lt;</span><span class=identifier>Rational</span><span class=special>&gt;)) </span><span class=comment>// __pow__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>abs</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) </span><span class=comment>// __abs__
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>str</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) </span><span class=comment>// __str__
</span><span class=special>;
</span></pre></code>
<p>
Need we say more?</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/lens.gif"></img> What is the business of <tt>operator&lt;&lt;</tt> <tt>.def(str(self))</tt>?
Well, the method <tt>str</tt> requires the <tt>operator&lt;&lt;</tt> to do its work (i.e.
<tt>operator&lt;&lt;</tt> is used by the method defined by def(str(self)). </td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_virtual_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,81 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Class Properties</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="class_data_members.html">
<link rel="next" href="inheritance.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Class Properties</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_data_members.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="inheritance.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Num
</span><span class=special>{
</span><span class=identifier>Num</span><span class=special>();
</span><span class=keyword>float </span><span class=identifier>get</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=keyword>float </span><span class=identifier>value</span><span class=special>);
</span><span class=special>...
</span><span class=special>};
</span></pre></code>
<p>
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
<tt>Num</tt> class using Boost.Python:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Num</span><span class=special>&gt;(</span><span class=string>&quot;Num&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>&quot;rovalue&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>get</span><span class=special>)
</span><span class=special>.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>&quot;value&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>get</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>set</span><span class=special>);
</span></pre></code>
<p>
And at last, in Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>Num</span><span class=special>()
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value </span><span class=special>= </span><span class=number>3.14
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value</span><span class=special>, </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>rovalue
</span><span class=special>(</span><span class=number>3.14</span><span class=special>, </span><span class=number>3.14</span><span class=special>)
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>rovalue </span><span class=special>= </span><span class=number>2.17 </span>#<span class=identifier>error</span><span class=special>!
</span></pre></code>
<p>
Take note that the class property <tt>rovalue</tt> is exposed as <b>read-only</b>
since the <tt>rovalue</tt> setter member function is not passed in:</p>
<code><pre>
<span class=special>.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>&quot;rovalue&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>get</span><span class=special>)
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_data_members.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="inheritance.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,227 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Class Virtual Functions</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="inheritance.html">
<link rel="next" href="class_operators_special_functions.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Class Virtual Functions</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="inheritance.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_operators_special_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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 <tt>Base</tt> class:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Base
</span><span class=special>{
</span><span class=keyword>virtual </span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() </span><span class=special>= </span><span class=number>0</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<p>
Since <tt>f</tt> is a pure virtual function, <tt>Base</tt> is now an abstract
class. Given an instance of our class, the free function <tt>call_f</tt>
calls some implementation of this virtual function in a concrete
derived class:</p>
<code><pre>
<span class=keyword>int </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>Base</span><span class=special>&amp; </span><span class=identifier>b</span><span class=special>) </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>b</span><span class=special>.</span><span class=identifier>f</span><span class=special>(); </span><span class=special>}
</span></pre></code>
<p>
To allow this function to be implemented in a Python derived class, we
need to create a class wrapper:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>BaseWrap </span><span class=special>: </span><span class=identifier>Base
</span><span class=special>{
</span><span class=identifier>BaseWrap</span><span class=special>(</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self_</span><span class=special>)
</span><span class=special>: </span><span class=identifier>self</span><span class=special>(</span><span class=identifier>self_</span><span class=special>) </span><span class=special>{}
</span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>call_method</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>self</span><span class=special>, </span><span class=string>&quot;f&quot;</span><span class=special>); </span><span class=special>}
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/lens.gif"></img> <b>member function and methods</b><br><br> Python, like
many object oriented languages uses the term <b>methods</b>. Methods
correspond roughly to C++'s <b>member functions</b> </td>
</tr>
</table>
<p>
Our class wrapper <tt>BaseWrap</tt> is derived from <tt>Base</tt>. Its overridden
virtual member function <tt>f</tt> in effect calls the corresponding method
of the Python object <tt>self</tt>, which is a pointer back to the Python
<tt>Base</tt> object holding our <tt>BaseWrap</tt> instance.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>Why do we need BaseWrap?</b><br><br>
<i>You may ask</i>, &quot;Why do we need the <tt>BaseWrap</tt> derived class? This could
have been designed so that everything gets done right inside of
Base.&quot;<br><br>
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. To unintrusively
hook into the virtual functions so that a Python override may be called, we
must use a derived class.<br><br>
Note however that you don't need to do this to get methods overridden
in Python to behave virtually when called <i>from</i> <b>Python</b>. The only
time you need to do the <tt>BaseWrap</tt> dance is when you have a virtual
function that's going to be overridden in Python and called
polymorphically <i>from</i> <b>C++</b>. </td>
</tr>
</table>
<p>
Wrapping <tt>Base</tt> and the free function <tt>call_f</tt>:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>, </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>noncopyable</span><span class=special>&gt;(</span><span class=string>&quot;Base&quot;</span><span class=special>, </span><span class=identifier>no_init</span><span class=special>)
</span><span class=special>;
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;call_f&quot;</span><span class=special>, </span><span class=identifier>call_f</span><span class=special>);
</span></pre></code>
<p>
Notice that we parameterized the <tt>class_</tt> template with <tt>BaseWrap</tt> as the
second parameter. What is <tt>noncopyable</tt>? Without it, the library will try
to create code for converting Base return values of wrapped functions to
Python. To do that, it needs Base's copy constructor... which isn't
available, since Base is an abstract class.</p>
<p>
In Python, let us try to instantiate our <tt>Base</tt> class:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>base </span><span class=special>= </span><span class=identifier>Base</span><span class=special>()
</span><span class=identifier>AttributeError</span><span class=special>: </span><span class=special>...
</span></pre></code>
<p>
Why is it an error? <tt>Base</tt> is an abstract class. As such it is advisable
to define the Python wrapper with <tt>no_init</tt> as we have done above. Doing
so will disallow abstract base classes such as <tt>Base</tt> to be instantiated.</p>
<a name="deriving_a_python_class"></a><h2>Deriving a Python class</h2><p>
Now, at last, we can even derive from our base class <tt>Base</tt> in Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=keyword>class </span><span class=identifier>Derived</span><span class=special>(</span><span class=identifier>Base</span><span class=special>):
</span><span class=special>... </span><span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
</span><span class=special>... </span><span class=keyword>return </span><span class=number>42
</span><span class=special>...
</span></pre></code>
<p>
Cool eh? A Python class deriving from a C++ class!</p>
<p>
Let's now make an instance of our Python class <tt>Derived</tt>:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>derived </span><span class=special>= </span><span class=identifier>Derived</span><span class=special>()
</span></pre></code>
<p>
Calling <tt>derived.f()</tt>:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>derived</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
</span><span class=number>42
</span></pre></code>
<p>
Will yield the expected result. Finally, calling calling the free function
<tt>call_f</tt> with <tt>derived</tt> as argument:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>derived</span><span class=special>)
</span><span class=number>42
</span></pre></code>
<p>
Will also yield the expected result.</p>
<p>
Here's what's happening:</p>
<ol><li><tt>call_f(derived)</tt> is called in Python</li><li>This corresponds to <tt>def(&quot;call_f&quot;, call_f);</tt>. Boost.Python dispatches this call.</li><li><tt>int call_f(Base&amp; b) { return b.f(); }</tt> accepts the call.</li><li>The overridden virtual function <tt>f</tt> of <tt>BaseWrap</tt> is called.</li><li><tt>call_method&lt;int&gt;(self, &quot;f&quot;);</tt> dispatches the call back to Python.</li><li><tt>def f(self): return 42</tt> is finally called.</li></ol><p>
Rewind back to our <tt>Base</tt> class, if its member function <tt>f</tt> was not
declared as pure virtual:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Base
</span><span class=special>{
</span><span class=keyword>virtual </span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=number>0</span><span class=special>; </span><span class=special>}
</span><span class=special>};
</span></pre></code>
<p>
And instead is implemented to return <tt>0</tt>, as shown above.</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>BaseWrap </span><span class=special>: </span><span class=identifier>Base
</span><span class=special>{
</span><span class=identifier>BaseWrap</span><span class=special>(</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self_</span><span class=special>)
</span><span class=special>: </span><span class=identifier>self</span><span class=special>(</span><span class=identifier>self_</span><span class=special>) </span><span class=special>{}
</span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>call_method</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>self</span><span class=special>, </span><span class=string>&quot;f&quot;</span><span class=special>); </span><span class=special>}
</span><span class=keyword>static </span><span class=keyword>int </span><span class=identifier>default_f</span><span class=special>(</span><span class=identifier>Base</span><span class=special>* </span><span class=identifier>b</span><span class=special>) </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>b</span><span class=special>-&gt;</span><span class=identifier>Base</span><span class=special>::</span><span class=identifier>f</span><span class=special>(); </span><span class=special>} </span><span class=comment>// &lt;&lt;=== added
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<p>
then, our Boost.Python wrapper:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>&gt;(</span><span class=string>&quot;Base&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>BaseWrap</span><span class=special>::</span><span class=identifier>default_f</span><span class=special>)
</span><span class=special>;
</span></pre></code>
<p>
Note that we are allowing <tt>Base</tt> objects to be instantiated this time,
unlike before where we specifically defined the <tt>class_&lt;Base&gt;</tt> with
<tt>no_init</tt>.</p>
<p>
In Python, the results would be as expected:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>base </span><span class=special>= </span><span class=identifier>Base</span><span class=special>()
</span><span class=special>&gt;&gt;&gt; </span><span class=keyword>class </span><span class=identifier>Derived</span><span class=special>(</span><span class=identifier>Base</span><span class=special>):
</span><span class=special>... </span><span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
</span><span class=special>... </span><span class=keyword>return </span><span class=number>42
</span><span class=special>...
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>derived </span><span class=special>= </span><span class=identifier>Derived</span><span class=special>()
</span></pre></code>
<p>
Calling <tt>base.f()</tt>:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>base</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
</span><span class=number>0
</span></pre></code>
<p>
Calling <tt>derived.f()</tt>:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>derived</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
</span><span class=number>42
</span></pre></code>
<p>
Calling <tt>call_f</tt>, passing in a <tt>base</tt> object:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>base</span><span class=special>)
</span><span class=number>0
</span></pre></code>
<p>
Calling <tt>call_f</tt>, passing in a <tt>derived</tt> object:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>derived</span><span class=special>)
</span><span class=number>42
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="inheritance.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_operators_special_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Constructors</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="exposing_classes.html">
<link rel="next" href="class_data_members.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Constructors</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exposing_classes.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_data_members.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Our previous example didn't have any explicit constructors.
Since <tt>World</tt> 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</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>planet </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
</span></pre></code>
<p>
We may wish to wrap a class with a non-default constructor. Let us
build on our previous example:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) </span><span class=special>{} </span><span class=comment>// added constructor
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) </span><span class=special>{ </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; </span><span class=special>}
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; </span><span class=special>}
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<p>
This time <tt>World</tt> has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose
it. We have to tell <tt>class_&lt;World&gt;</tt> about the constructor we want to
expose instead.</p>
<code><pre>
<span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>World</span><span class=special>&gt;(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;greet&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;set&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
</span><span class=special>;
</span><span class=special>}
</span></pre></code>
<p>
<tt>init&lt;std::string&gt;()</tt> exposes the constructor taking in a
<tt>std::string</tt> (in Python, constructors are spelled
&quot;<tt>&quot;__init__&quot;</tt>&quot;).</p>
<p>
We can expose additional constructors by passing more <tt>init&lt;...&gt;</tt>s to
the <tt>def()</tt> member function. Say for example we have another World
constructor taking in two doubles:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>World</span><span class=special>&gt;(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special>&lt;</span><span class=keyword>double</span><span class=special>, </span><span class=keyword>double</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;greet&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;set&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
</span><span class=special>;
</span></pre></code>
<p>
On the other hand, if we do not wish to expose any constructors at
all, we may use <tt>no_init</tt> instead:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Abstract</span><span class=special>&gt;(</span><span class=string>&quot;Abstract&quot;</span><span class=special>, </span><span class=identifier>no_init</span><span class=special>)
</span></pre></code>
<p>
This actually adds an <tt>__init__</tt> method which always raises a
Python RuntimeError exception.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exposing_classes.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_data_members.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,118 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Default Arguments</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="call_policies.html">
<link rel="next" href="object_interface.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Default Arguments</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="call_policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="object_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
pointers carry no default argument info. Take a function <tt>f</tt> with default
arguments:</p>
<code><pre>
<span class=keyword>int </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>double </span><span class=special>= </span><span class=number>3.14</span><span class=special>, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=special>= </span><span class=string>&quot;hello&quot;</span><span class=special>);
</span></pre></code>
<p>
But the type of a pointer to the function <tt>f</tt> has no information
about its default arguments:</p>
<code><pre>
<span class=keyword>int</span><span class=special>(*</span><span class=identifier>g</span><span class=special>)(</span><span class=keyword>int</span><span class=special>,</span><span class=keyword>double</span><span class=special>,</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) </span><span class=special>= </span><span class=identifier>f</span><span class=special>; </span><span class=comment>// defaults lost!
</span></pre></code>
<p>
When we pass this function pointer to the <tt>def</tt> function, there is no way
to retrieve the default arguments:</p>
<code><pre>
<span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=identifier>f</span><span class=special>); </span><span class=comment>// defaults lost!
</span></pre></code>
<p>
Because of this, when wrapping C++ code in earlier versions of
Boost.Python, we had to resort to writing thin wrappers:</p>
<code><pre>
<span class=comment>// write &quot;thin wrappers&quot;
</span><span class=keyword>int </span><span class=identifier>f1</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>x</span><span class=special>) </span><span class=special>{ </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>); </span><span class=special>}
</span><span class=keyword>int </span><span class=identifier>f2</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>x</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>y</span><span class=special>) </span><span class=special>{ </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>y</span><span class=special>); </span><span class=special>}
</span><span class=comment>/*...*/
// in module init
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=identifier>f</span><span class=special>); </span><span class=comment>// all arguments
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=identifier>f2</span><span class=special>); </span><span class=comment>// two arguments
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;f&quot;</span><span class=special>, </span><span class=identifier>f1</span><span class=special>); </span><span class=comment>// one argument
</span></pre></code>
<p>
When you want to wrap functions (or member functions) that either:</p>
<ul><li>have default arguments, or</li><li>are overloaded with a common sequence of initial arguments</li></ul><p>
Boost.Python now has a way to make it easier.</p>
<p>
For instance, given a function:</p>
<code><pre>
<span class=keyword>int </span><span class=identifier>foo</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>b </span><span class=special>= </span><span class=number>1</span><span class=special>, </span><span class=keyword>unsigned </span><span class=identifier>c </span><span class=special>= </span><span class=number>2</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>d </span><span class=special>= </span><span class=number>3</span><span class=special>);
</span></pre></code>
<p>
The macro invocation:</p>
<code><pre>
<span class=identifier>BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class=special>(</span><span class=identifier>foo_overloads</span><span class=special>, </span><span class=identifier>foo</span><span class=special>, </span><span class=number>1</span><span class=special>, </span><span class=number>4</span><span class=special>)
</span></pre></code>
<p>
Will automatically create the thin wrappers for us. This macro will create
a class <tt>foo_overloads</tt> that can be passed on to <tt>def(...)</tt>. The third
and fourth macro argument are the minimum arguments and maximum arguments,
respectively. In our <tt>foo</tt> function the minimum number of arguments is 1
and the maximum number of arguments is 4. The <tt>def(...)</tt> function will
automatically add all the foo variants for us:</p>
<code><pre>
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;foo&quot;</span><span class=special>, </span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>foo_overloads</span><span class=special>());
</span></pre></code>
<p>
A similar facility is provided for class constructors, again, with
default arguments or a sequence of overloads. Remember init&lt;...&gt;? For example,
given a class X with a constructor:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>X
</span><span class=special>{
</span><span class=identifier>X</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>b </span><span class=special>= </span><span class=literal>'D'</span><span class=special>, </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>c </span><span class=special>= </span><span class=string>&quot;constructor&quot;</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>d </span><span class=special>= </span><span class=number>0.0</span><span class=special>);
</span><span class=comment>/*...*/
</span><span class=special>}
</span></pre></code>
<p>
You can easily add this constructor to Boost.Python in one shot:</p>
<code><pre>
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>, </span><span class=identifier>optional</span><span class=special>&lt;</span><span class=keyword>char</span><span class=special>, </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>, </span><span class=keyword>double</span><span class=special>&gt; </span><span class=special>&gt;())
</span></pre></code>
<p>
Notice the use of <tt>init&lt;...&gt;</tt> and <tt>optional&lt;...&gt;</tt> to signify the default
(optional arguments).</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="call_policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="object_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,117 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Derived Object types</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="basic_interface.html">
<link rel="next" href="extracting_c___objects.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Derived Object types</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="basic_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="extracting_c___objects.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Boost.Python comes with a set of derived <tt>object</tt> types corresponding to
that of Python's:</p>
<ul><li>list</li><li>dict</li><li>tuple</li><li>str</li><li>long_</li><li>enum</li></ul><p>
These derived <tt>object</tt> types act like real Python types. For instance:</p>
<code><pre>
<span class=identifier>str</span><span class=special>(</span><span class=number>1</span><span class=special>) </span><span class=special>==&gt; </span><span class=string>&quot;1&quot;
</span></pre></code>
<p>
Wherever appropriate, a particular derived <tt>object</tt> has corresponding
Python type's methods. For instance, <tt>dict</tt> has a <tt>keys()</tt> method:</p>
<code><pre>
<span class=identifier>d</span><span class=special>.</span><span class=identifier>keys</span><span class=special>()
</span></pre></code>
<p>
<tt>make_tuple</tt> is provided for declaring <i>tuple literals</i>. Example:</p>
<code><pre>
<span class=identifier>make_tuple</span><span class=special>(</span><span class=number>123</span><span class=special>, </span><span class=literal>'D'</span><span class=special>, </span><span class=string>&quot;Hello, World&quot;</span><span class=special>, </span><span class=number>0.0</span><span class=special>);
</span></pre></code>
<p>
In C++, when Boost.Python <tt>object</tt>s are used as arguments to functions,
subtype matching is required. For example, when a function <tt>f</tt>, as
declared below, is wrapped, it will only accept instances of Python's
<tt>str</tt> type and subtypes.</p>
<code><pre>
<span class=keyword>void </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>str </span><span class=identifier>name</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>object </span><span class=identifier>n2 </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;upper&quot;</span><span class=special>)(); </span><span class=comment>// NAME = name.upper()
</span><span class=identifier>str </span><span class=identifier>NAME </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>upper</span><span class=special>(); </span><span class=comment>// better
</span><span class=identifier>object </span><span class=identifier>msg </span><span class=special>= </span><span class=string>&quot;%s is bigger than %s&quot; </span><span class=special>% </span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>NAME</span><span class=special>,</span><span class=identifier>name</span><span class=special>);
</span><span class=special>}
</span></pre></code>
<p>
In finer detail:</p>
<code><pre>
<span class=identifier>str </span><span class=identifier>NAME </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>upper</span><span class=special>();
</span></pre></code>
<p>
Illustrates that we provide versions of the str type's methods as C++
member functions.</p>
<code><pre>
<span class=identifier>object </span><span class=identifier>msg </span><span class=special>= </span><span class=string>&quot;%s is bigger than %s&quot; </span><span class=special>% </span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>NAME</span><span class=special>,</span><span class=identifier>name</span><span class=special>);
</span></pre></code>
<p>
Demonstrates that you can write the C++ equivalent of <tt>&quot;format&quot; % x,y,z</tt>
in Python, which is useful since there's no easy way to do that in std C++.</p>
<p>
<img src="theme/alert.gif"></img> <b>Beware</b> the common pitfall of forgetting that the constructors
of most of Python's mutable types make copies, just as in Python.</p>
<p>
Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>dict</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__</span><span class=special>) </span>#<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span>#<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
</span></pre></code>
<p>
C++:</p>
<code><pre>
<span class=identifier>dict </span><span class=identifier>d</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;__dict__&quot;</span><span class=special>)); </span>#<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
</span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span><span class=special>= </span><span class=number>3</span><span class=special>; </span>#<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
</span></pre></code>
<a name="class__lt_t_gt__as_objects"></a><h2>class_&lt;T&gt; as objects</h2><p>
Due to the dynamic nature of Boost.Python objects, any <tt>class_&lt;T&gt;</tt> may
also be one of these types! The following code snippet wraps the class
(type) object.</p>
<p>
We can use this to create wrapped instances. Example:</p>
<code><pre>
<span class=identifier>object </span><span class=identifier>vec345 </span><span class=special>= </span><span class=special>(
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Vec2</span><span class=special>&gt;(</span><span class=string>&quot;Vec2&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt;</span><span class=keyword>double</span><span class=special>, </span><span class=keyword>double</span><span class=special>&gt;())
</span><span class=special>.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>&quot;length&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Point</span><span class=special>::</span><span class=identifier>length</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>&quot;angle&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>Point</span><span class=special>::</span><span class=identifier>angle</span><span class=special>)
</span><span class=special>)(</span><span class=number>3.0</span><span class=special>, </span><span class=number>4.0</span><span class=special>);
</span><span class=identifier>assert</span><span class=special>(</span><span class=identifier>vec345</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;length&quot;</span><span class=special>) </span><span class=special>== </span><span class=number>5.0</span><span class=special>);
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="basic_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="extracting_c___objects.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,78 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Embedding</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="next" href="using_the_interpreter.html">
</head>
<body>
<table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
<tr>
<td width="10">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Embedding</b></font>
</td>
<td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" align="right" border="0"></a></td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="using_the_interpreter.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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 <i>embed</i> the Python interpreter into your C++ program. </p>
<p>
Currently, Boost.Python does not directly support everything you'll need when embedding. Therefore you'll need to use the <a href="http://www.python.org/doc/current/api/api.html">
Python/C API</a> 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... <img src="theme/smiley.gif"></img></p>
<a name="building_embedded_programs"></a><h2>Building embedded programs</h2><p>
To be able to use embedding in your programs, they have to be linked to both Boost.Python's and Python's static link library. </p>
<p>
Boost.Python's static link library comes in two variants. Both are located in Boost's <tt>/libs/python/build/bin-stage</tt> subdirectory. On Windows, the variants are called <tt>boost_python.lib</tt> (for release builds) and <tt>boost_python_debug.lib</tt> (for debugging). If you can't find the libraries, you probably haven't built Boost.Python yet. See <a href="../../building.html">
Building and Testing</a> on how to do this.</p>
<p>
Python's static link library can be found in the <tt>/libs</tt> subdirectory of your Python directory. On Windows it is called pythonXY.lib where X.Y is your major Python version number. </p>
<p>
Additionally, Python's <tt>/include</tt> subdirectory has to be added to your include path.</p>
<p>
In a Jamfile, all the above boils down to:</p>
<code><pre>
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) ;
</pre></code><a name="getting_started"></a><h2>Getting started</h2><p>
Being able to build is nice, but there is nothing to build yet. Embedding the Python interpreter into one of your C++ programs requires these 4 steps:</p>
<ol><li>#include <tt>&lt;boost/python.hpp&gt;</tt><br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
Py_Initialize</a>() to start the interpreter and create the <tt>__main__</tt> module.<br><br></li><li>Call other Python C API routines to use the interpreter.<br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
Py_Finalize</a>() to stop the interpreter and release its resources.</li></ol><p>
(Of course, there can be other C++ code between all of these steps.)</p>
<blockquote><p><i><b>Now that we can embed the interpreter in our programs, lets see how to put it to use...</b></i></p></blockquote><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="using_the_interpreter.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 Dirk Gerrits <br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,190 +0,0 @@
[doc Tutorial extension draft]
[/ this probably needs to be merged into quickstart.txt ]
[def __note__ [$theme/note.gif]]
[def __alert__ [$theme/alert.gif]]
[def __detail__ [$theme/lens.gif]]
[def __tip__ [$theme/bulb.gif]]
[def :-) [$theme/smiley.gif]]
[def Py_Initialize [@http://www.python.org/doc/current/api/initialization.html#l2h-652 Py_Initialize]]
[def Py_Finalize [@http://www.python.org/doc/current/api/initialization.html#l2h-656 Py_Finalize]]
[def PyRun_String [@http://www.python.org/doc/current/api/veryhigh.html#l2h-55 PyRun_String]]
[def PyRun_File [@http://www.python.org/doc/current/api/veryhigh.html#l2h-56 PyRun_File]]
[def Py_eval_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-58 Py_eval_input]]
[def Py_file_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-59 Py_file_input]]
[def Py_single_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-60 Py_single_input]]
[def Py_XINCREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-65 Py_XINCREF]]
[def Py_XDECREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-67 Py_XDECREF]]
[def PyImport_AppendInittab [@http://www.python.org/doc/current/api/importing.html#l2h-137 PyImport_AppendInittab]]
[def PyImport_AddModule [@http://www.python.org/doc/current/api/importing.html#l2h-125 PyImport_AddModule]]
[def PyModule_New [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-591 PyModule_New]]
[def PyModule_GetDict [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-594 PyModule_GetDict]]
[page:0 Embedding]
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 ['embed] the Python interpreter into your C++ program.
Currently, Boost.Python does not directly support everything you'll need when embedding. Therefore you'll need to use the [@http://www.python.org/doc/current/api/api.html Python/C API] 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... :-)
[h2 Building embedded programs]
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.
Boost.Python's static link library comes in two variants. Both are located in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the variants are called [^boost_python.lib] (for release builds) and [^boost_python_debug.lib] (for debugging). If you can't find the libraries, you probably haven't built Boost.Python yet. See [@../../building.html Building and Testing] on how to do this.
Python's static link library can be found in the [^/libs] subdirectory of your Python directory. On Windows it is called pythonXY.lib where X.Y is your major Python version number.
Additionally, Python's [^/include] subdirectory has to be added to your include path.
In a Jamfile, all the above boils down to:
[pre
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
<find-library>boost_python <library-path>c:\boost\libs\python
$(PYTHON_PROPERTIES)
<library-path>$(PYTHON_LIB_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
]
[h2 Getting started]
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:
# '''#include''' [^<boost/python.hpp>][br][br]
# Call Py_Initialize() to start the interpreter and create the [^__main__] module.[br][br]
# Call other Python C API routines to use the interpreter.[br][br]
# Call Py_Finalize() to stop the interpreter and release its resources.
(Of course, there can be other C++ code between all of these steps.)
[:['[*Now that we can embed the interpreter in our programs, lets see how to put it to use...]]]
[page:1 Using the interpreter]
As you probably already know, objects in Python are reference-counted. Naturally, the [^PyObject]s of the Python/C API are also reference-counted. There is a difference however. While the reference-counting is fully automatic in Python, the Python/C API requires you to do it [@http://www.python.org/doc/current/api/refcounts.html by hand]. This is messy and especially hard to get right in the presence of C++ exceptions. Fortunately Boost.Python provides the [@../../v2/handle.html handle] class template to automate the process.
[h2 Reference-counting handles]
There are two ways in which a function in the Python/C API can return a [^PyObject*]: as a ['borrowed reference] or as a ['new reference]. 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.
For a function returning a ['borrowed reference] we'll have to tell the [^handle] that the [^PyObject*] is borrowed with the aptly named [@../../v2/handle.html#borrowed-spec borrowed] function. Two functions returning borrowed references are PyImport_AddModule and PyModule_GetDict. 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 [^__main__] module:
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
handle<> main_namespace(borrowed( PyModule_GetDict(main_module.get()) ));
Because the Python/C API doesn't know anything about [^handle]s, we used the [@../../v2/handle.html#handle-spec-observers get] member function to retrieve the [^PyObject*] from which the [^handle] was constructed.
For a function returning a ['new reference] we can just create a [^handle] out of the raw [^PyObject*] without wrapping it in a call to borrowed. One such function that returns a new reference is PyRun_String which we'll discuss in the next section.
[blurb __detail__ [*Handle is a class ['template], so why haven't we been using any template parameters?][br]
[br]
[^handle] has a single template parameter specifying the type of the managed object. This type is [^PyObject] 99% of the time, so the parameter was defaulted to [^PyObject] for convenience. Therefore we can use the shorthand [^handle<>] instead of the longer, but equivalent, [^handle<PyObject>].
]
[h2 Running Python code]
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 [@http://www.python.org/doc/current/api/veryhigh.html here]. They all work similarly so we will look at only one of them, namely:
PyObject* PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
PyRun_String takes the code to execute as a null-terminated (C-style) string in its [^str] parameter. The function returns a new reference to a Python object. Which object is returned depends on the [^start] paramater.
The [^start] parameter is the start symbol from the Python grammar to use for interpreting the code. The possible values are:
[table Start symbols
[Py_eval_input] [for interpreting isolated expressions]
[Py_file_input] [for interpreting sequences of statements]
[Py_single_input] [for interpreting a single statement]
]
When using Py_eval_input, the input string must contain a single expression and its result is returned. When using Py_file_input, the string can contain an abitrary number of statements and None is returned. Py_single_input works in the same way as Py_file_input but only accepts a single statement.
Lastly, the [^globals] and [^locals] 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 [^__main__] module for both parameters.
We have already seen how to get the [^__main__] module's namespace so let's run some Python code in it:
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
handle<> main_namespace(borrowed( PyModule_GetDict(main_module.get()) ));
handle<>( PyRun_String("hello = file('hello.txt', 'w')\n"
"hello.write('Hello world!')\n"
"hello.close()", Py_file_input,
main_namespace.get(), main_namespace.get()) );
This should create a file called 'hello.txt' in the current directory containing a phrase that is well-known in programming circles.
__note__ [*Note] that we wrap the return value of PyRun_String in a (nameless) [^handle] even though we are not interested in it. If we didn't do this, the the returned object would be kept alive unnecessarily. Unless you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
[h2 Beyond handles]
It's nice that [^handle] manages the reference counting details for us, but other than that it doesn't do much. Often we'd like to have a more useful class to manipulate Python objects. But we have already seen such a class in the [@object_interface.html previous section]: the aptly named [^object] class and it's derivatives. What we haven't seen, is that they can be constructed from a [^handle]. The following examples should illustrate this fact:
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
main_namespace dict(handle<>(borrowed( PyModule_GetDict(main_module.get()) )));
handle<>( PyRun_String("result = 5 ** 2", Py_file_input,
main_namespace.ptr(), main_namespace.ptr()) );
int five_squared = extract<int>( main_namespace["result"] );
Here we create a dictionary object for the [^__main__] 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 PyRun_String return the result directly with Py_eval_input:
object result(handle<>( PyRun_String("5 ** 2", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr()) ));
int five_squared = extract<int>(result);
__note__ [*Note] that [^object]'s member function to return the wrapped [^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you take into account the different functions that [^object] and [^handle] perform.
[h2 Exception handling]
If an exception occurs in the execution of some Python code, the PyRun_String function returns a null pointer. Constructing a [^handle] out of this null pointer throws [@../../v2/errors.html#error_already_set-spec error_already_set], so basically, the Python exception is automatically translated into a C++ exception when using [^handle]:
try
{
object result(handle<>( PyRun_String("5/0", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr()) ));
// execution will never get here:
int five_divided_by_zero = extract<int>(result);
}
catch(error_already_set)
{
// handle the exception in some way
}
The [^error_already_set] exception class doesn't carry any information in itself. To find out more about the Python exception that occurred, you need to use the [@http://www.python.org/doc/api/exceptionHandling.html exception handling functions] of the Python/C API in your catch-statement. This can be as simple as calling [@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to print the exception's traceback to the console, or comparing the type of the exception with those of the [@http://www.python.org/doc/api/standardExceptions.html standard exceptions]:
catch(error_already_set)
{
if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
{
// handle ZeroDivisionError specially
}
else
{
// print all other errors to stderr
PyErr_Print();
}
}
(To retrieve even more information from the exception you can use some of the other exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
If you'd rather not have [^handle] throw a C++ exception when it is constructed, you can use the [@../../v2/handle.html#allow_null-spec allow_null] function in the same way you'd use borrowed:
handle<> result(allow_null( PyRun_String("5/0", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr()) ));
if (!result)
// Python exception occurred
else
// everything went okay, it's safe to use the result

View File

@@ -1,128 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Embedding basics</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="embedding.html">
<link rel="next" href="embedding_with_boost_python.html">
</head>
<body>
<table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
<tr>
<td width="10">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Embedding basics</b></font>
</td>
<td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" align="right" border="0"></a></td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="embedding_with_boost_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<a name="manual_reference_counting"></a><h2>Manual reference counting</h2><p>
Most things in Python are objects. Therefore it is only natural that many of the Python C API functions operate on Python objects. Because C/C++ can't work with Python objects directly, the API defines a PyObject structure and a lot of functions to operate on PyObject pointers. </p>
<p>
An important property of Python objects, and therefore of PyObjects, is that they are reference counted. This has major advantages compared to 'dumb' copying: it requiring less memory and it avoids unnecessary copying overhead. However, there is a downside as well. Although the reference counting is transparent from the Python-side, it is quite explicit in the C API. In other words you must increase and decrease the reference counts of PyObjects <b>manually</b> using the <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-65">
Py_XINCREF</a> and <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-67">
Py_XDECREF</a> macros. This is cumbersome, and if you don't do it properly some objects might be released when you still need them, or not be released at all. </p>
<p>
I will briefly explain how to update the reference counts correctly, but I'll soon show a better way to do things.</p>
<p>
The API functions that return PyObject pointers are listed in the Python C API documentation as either returning a <i>borrowed</i> or a <i>new</i> reference. The difference is in <i>reference ownership</i>. </p>
<p>
When a <i>new</i> reference is returned, you own that reference. Therefore you don't need to worry about the object being deallocated while you still need it. You do need to decrease the reference count when you are done with it however, otherwise the object will never be deallocated: you'll have a <i>resource leak</i>. </p>
<p>
Here's a simple example:</p>
<code><pre>
<span class=comment>// Create a new tuple of 3 elements long
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>my_tuple </span><span class=special>= </span><span class=identifier>PyTuple_New</span><span class=special>(</span><span class=number>3</span><span class=special>);
</span><span class=special>... </span><span class=comment>// Use my_tuple here
// We're done with the tuple
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>my_tuple</span><span class=special>);
</span></pre></code>
<p>
When a <i>borrowed</i> reference is returned, you do not have ownership of the reference. So if you just want to discard the return value, there is nothing you have to do: you didn't own it anyway. If want to use it however, you'll first have to increase its reference count (to prevent the object's deletion). Then later on when you are done with itm you'll need to decrease the reference count again. Here's another example:</p>
<code><pre>
<span class=comment>// Retrieve the first item in the tuple
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>first </span><span class=special>= </span><span class=identifier>PyTuple_GetItem</span><span class=special>(</span><span class=identifier>my_tuple</span><span class=special>, </span><span class=number>0</span><span class=special>);
</span><span class=identifier>Py_XINCREF</span><span class=special>(</span><span class=identifier>first</span><span class=special>);
</span><span class=special>... </span><span class=comment>// Use first here
// We're done with the first tuple item
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>first</span><span class=special>);
</span></pre></code>
<p>
While this certainly works, it's hardly elegant and it's easy to make mistakes, especially when there are multiple execution paths.</p>
<a name="running_python_code_from_c__"></a><h2>Running Python code from C++</h2><p>
To run Python code from C++ there is a family of functions in the API starting with the PyRun_ prefix. You can find the list of these fuctions <a href="http://www.python.org/doc/current/api/veryhigh.html">
here</a>. I shall discuss one of them, the others work very similarly.</p>
<code><pre>
<span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=keyword>char </span><span class=special>*</span><span class=identifier>str</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>start</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>globals</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>locals</span><span class=special>)
</span></pre></code>
<p>
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> takes the code to execute as a null-terminated (C-style) string in its <tt>str</tt> parameter. The function returns a new reference to the Python object which results from executing the code. If a Python exception occurred during execution, the null pointer is returned.</p>
<p>
The <tt>start</tt> parameter is the start symbol from the Python grammar to use for interpreting the code. The possible values are:</p>
<table width="90%" border="0" align="center"> <tr>
<td class="table_title" colspan="6">
Start symbols </td>
</tr>
<tr><tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
Py_eval_input</a></td><td class="table_cells">for interpreting isolated expressions</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
Py_file_input</a></td><td class="table_cells">for interpreting sequences of statements</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">
Py_single_input</a></td><td class="table_cells">for interpreting a single statement</td></tr></table>
<p>
Lastly, the <tt>globals</tt> and <tt>locals</tt> 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 running module for both <tt>globals</tt> and <tt>locals</tt>.</p>
<p>
So how do we get a module's namespace dictionary? First we need to get a reference to the module. The function to do this is <a href="http://www.python.org/doc/current/api/importing.html#l2h-125">
PyImport_AddModule</a>. Contrary to what you might guess from its name, it returns a borrowed reference to an <b>existing</b> module. </p>
<p>
Then once we have a reference to the module, we can use <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594">
PyModule_GetDict</a> to get a borrowed reference to the module's namespace dictionary.</p>
<p>
Since the running module is usually the <tt>__main__</tt> module created upon interpreter initialization, the code to execute a Python program from a string becomes:</p>
<code><pre>
<span class=comment>// Get the __main__ module namespace
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>main_module </span><span class=special>= </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>);
</span><span class=identifier>Py_XINCREF</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>);
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>main_namespace </span><span class=special>= </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>);
</span><span class=identifier>Py_XINCREF</span><span class=special>(</span><span class=identifier>main_namespace</span><span class=special>);
</span><span class=comment>// Run a single Python expression and retrieve the result
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>result </span><span class=special>= </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;1 + 1&quot;</span><span class=special>,
</span><span class=identifier>Py_eval_input</span><span class=special>, </span><span class=identifier>main_namespace</span><span class=special>, </span><span class=identifier>main_namespace</span><span class=special>);
</span><span class=special>... </span><span class=comment>// Use the result
// Cleanup
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>result</span><span class=special>);
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>main_namespace</span><span class=special>);
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>);
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/alert.gif"></img> <b>Warning</b><br><br>
Be careful about what Python code you run and where. Running the addition above on your computer can hardly do any harm. But letting users run arbitrary Python code through your program which is running on a webserver can be a security risk.
</td>
</tr>
</table>
<blockquote><p><i><b>Next up: How Boost.Python can simplify embedding...</b></i></p></blockquote><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="embedding_with_boost_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 Dirk Gerrits <br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Embedding with Boost.Python</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="embedding_basics.html">
</head>
<body>
<table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
<tr>
<td width="10">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Embedding with Boost.Python</b></font>
</td>
<td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" align="right" border="0"></a></td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding_basics.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<a name="boost_python_to_the_rescue"></a><h2>Boost.Python to the rescue</h2><p>
Now we get to the good news. If you don't want to do all the error prone reference counting yourself, you can let Boost.Python do all the work. First include <tt>&lt;boost/python.hpp&gt;</tt> instead of <tt>&quot;Python.h&quot;</tt> and link to <tt>boost_python.lib</tt> (or <tt>boost_python_debug.lib</tt>) instead of <tt>pythonXY.lib</tt>. Then all we really need to do is replace every PyObject* with <a href="../../v2/handle.html">
handle</a>&lt;&gt; and we can remove all the <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-65">
Py_XINCREF</a>s and <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-67">
Py_XDECREF</a>s! All the reference counting will be done automagically through the power of the <a href="http://sourceforge.net/docman/display_doc.php?docid=8673&amp;group_id=9028">
Resource Acquisition Is Initialization</a> idiom. </p>
<p>
We still need a way to differentiate between new and borrowed references though. Luckily, this is pretty straightforward using the <a href="../../v2/handle.html#borrowed-spec">
borrowed</a> function. Let's rewrite the example to run Python code from a string to use <a href="../../v2/handle.html">
handle</a>s:</p>
<code><pre>
<span class=comment>// Get the __main__ module namespace
</span><span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_module</span><span class=special>( </span><span class=identifier>borrowed</span><span class=special>(</span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>)) </span><span class=special>);
</span><span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_namespace</span><span class=special>( </span><span class=identifier>borrowed</span><span class=special>(</span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>)) </span><span class=special>);
</span><span class=comment>// Run a single Python expression and retrieve the result
</span><span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>result</span><span class=special>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;1 + 1&quot;</span><span class=special>,
</span><span class=identifier>Py_eval_input</span><span class=special>, </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>get</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) </span><span class=special>);
</span><span class=special>... </span><span class=comment>// Use the result
</span></pre></code>
<p>
The <a href="../../v2/handle.html#handle-spec-observers">
get</a>() member function used here returns the raw PyObject* that is held by the <a href="../../v2/handle.html">
handle</a>.</p>
<a name="boost_python_modules_in_an_embedded_program"></a><h2>Boost.Python modules in an embedded program</h2><p>
Now that we know how to call Python code from C++ and C++ code from Python, how about doing both at the same time? Sometimes you might want to call Python code from C++ and have that Python code call C++ code again. </p>
<p>
If you built your Boost.Python module and put it in the proper directory, you can just use it in your embedded Python code as you would in a standalone Python program. The embedded interpreter will be able to find your module just as the standalone interpreter would.</p>
<p>
However, you can also define the Boost.Python module in the same program that embeds the Python interpreter. Then you won't have to build the module seperately and place it in the proper directory. This also prevents others from using your module in their own Python code. (Unless they start taking your executable apart that is. <img src="theme/smiley.gif"></img>) </p>
<p>
Doing this is relatively straightforward. You just define your Boost.Python module as usual and use the basic embedding steps described earlier. However, before calling <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
Py_Initialize</a> you call <a href="http://www.python.org/doc/current/api/importing.html#l2h-137">
PyImport_AppendInittab</a> first. </p>
<p>
This function takes the name and <a href="../../v2/module.html#BOOST_PYTHON_MODULE-spec">
initialization function</a> of your module as parameters and adds the module to the interpreter's list of builtin modules. So when the Python interpreter comes across an import statement, it will find the module in its list of builtin modules instead of (unsuccessfully) searching for it in the Python directory.</p>
<p>
Your program will look something like this:</p>
<code><pre>
<span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>my_module</span><span class=special>)
</span><span class=special>{
</span><span class=special>...
</span><span class=special>}
</span><span class=special>...
</span><span class=identifier>PyImport_AppendInittab</span><span class=special>(</span><span class=string>&quot;my_module&quot;</span><span class=special>, </span><span class=identifier>initmy_module</span><span class=special>);
</span><span class=identifier>Py_Initialize</span><span class=special>();
</span><span class=special>...
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/alert.gif"></img> <b>Warning</b><br><br>
When creating Boost.Python modules in the same program that embeds interpreter, you must <b><i>not</i></b> call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
Py_Finalize</a>. Boost.Python keeps some PyObject references alive in global data structures, and when those go out of scope after interpreter finalization, Python crashes. This will be fixed in the future. Stay tuned.
</td>
</tr>
</table>
<a name="additional_reading"></a><h2>Additional reading</h2><p>
A more elaborate example showing these techniques is located at <a href="../../../test/embedding.cpp">
/libs/python/test/embedding.cpp</a>. </p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding_basics.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 Dirk Gerrits <br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,95 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Enums</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="extracting_c___objects.html">
<link rel="next" href="iterators.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Enums</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="extracting_c___objects.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="iterators.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Boost.Python has a nifty facility to capture and wrap C++ enums. While
Python has no <tt>enum</tt> type, we'll often want to expose our C++ enums to
Python as an <tt>int</tt>. 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:</p>
<code><pre>
<span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
</span></pre></code>
<p>
the construct:</p>
<code><pre>
<span class=identifier>enum_</span><span class=special>&lt;</span><span class=identifier>choice</span><span class=special>&gt;(</span><span class=string>&quot;choice&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>value</span><span class=special>(</span><span class=string>&quot;red&quot;</span><span class=special>, </span><span class=identifier>red</span><span class=special>)
</span><span class=special>.</span><span class=identifier>value</span><span class=special>(</span><span class=string>&quot;blue&quot;</span><span class=special>, </span><span class=identifier>blue</span><span class=special>)
</span><span class=special>;
</span></pre></code>
<p>
can be used to expose to Python. The new enum type is created in the
current <tt>scope()</tt>, which is usually the current module. The snippet above
creates a Python class derived from Python's <tt>int</tt> type which is
associated with the C++ type passed as its first parameter.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/lens.gif"></img> <b>what is a scope?</b><br><br> The scope is a class that has an
associated global Python object which controls the Python namespace in
which new extension classes and wrapped functions will be defined as
attributes. Details can be found <a href="../../v2/scope.html">
here</a>. </td>
</tr>
</table>
<p>
You can access those values in Python as</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>my_module</span><span class=special>.</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red
</span><span class=identifier>my_module</span><span class=special>.</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red
</span></pre></code>
<p>
where my_module is the module where the enum is declared. You can also
create a new scope around a class:</p>
<code><pre>
<span class=identifier>scope </span><span class=identifier>in_X</span><span class=special>(</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>X</span><span class=special>&gt;(</span><span class=string>&quot;X&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>( </span><span class=special>... </span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>( </span><span class=special>... </span><span class=special>)
</span><span class=special>);
</span><span class=comment>// Expose X::nested as X.nested
</span><span class=identifier>enum_</span><span class=special>&lt;</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>nested</span><span class=special>&gt;(</span><span class=string>&quot;nested&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>value</span><span class=special>(</span><span class=string>&quot;red&quot;</span><span class=special>, </span><span class=identifier>red</span><span class=special>)
</span><span class=special>.</span><span class=identifier>value</span><span class=special>(</span><span class=string>&quot;blue&quot;</span><span class=special>, </span><span class=identifier>blue</span><span class=special>)
</span><span class=special>;
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="extracting_c___objects.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="iterators.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,60 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Exception Translation</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="iterators.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exception Translation</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<p>
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:</p>
<code><pre>
<span class=identifier>raise </span><span class=identifier>RuntimeError</span><span class=special>, </span><span class=literal>'unidentifiable C++ Exception'
</span></pre></code>
<p>
Users may provide custom translation. Here's an example:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>PodBayDoorException</span><span class=special>;
</span><span class=keyword>void </span><span class=identifier>translator</span><span class=special>(</span><span class=identifier>PodBayDoorException</span><span class=special>&amp; </span><span class=identifier>x</span><span class=special>) </span><span class=special>{
</span><span class=identifier>PyErr_SetString</span><span class=special>(</span><span class=identifier>PyExc_UserWarning</span><span class=special>, </span><span class=string>&quot;I'm sorry Dave...&quot;</span><span class=special>);
</span><span class=special>}
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>kubrick</span><span class=special>) </span><span class=special>{
</span><span class=identifier>register_exception_translator</span><span class=special>&lt;
</span><span class=identifier>PodBayDoorException</span><span class=special>&gt;(</span><span class=identifier>translator</span><span class=special>);
</span><span class=special>...
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,79 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Exposing Classes</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="building_hello_world.html">
<link rel="next" href="constructors.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exposing Classes</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="building_hello_world.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="constructors.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Now let's expose a C++ class to Python.</p>
<p>
Consider a C++ class/struct that we want to expose to Python:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) </span><span class=special>{ </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; </span><span class=special>}
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; </span><span class=special>}
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
</span><span class=special>};
</span></pre></code>
<p>
We can expose this to Python by writing a corresponding Boost.Python
C++ Wrapper:</p>
<code><pre>
<span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>World</span><span class=special>&gt;(</span><span class=string>&quot;World&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;greet&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;set&quot;</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
</span><span class=special>;
</span><span class=special>}
</span></pre></code>
<p>
Here, we wrote a C++ class wrapper that exposes the member functions
<tt>greet</tt> and <tt>set</tt>. Now, after building our module as a shared library, we
may use our class <tt>World</tt> in Python. Here's a sample Python session:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>planet </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>planet</span><span class=special>.</span><span class=identifier>set</span><span class=special>(</span><span class=literal>'howdy'</span><span class=special>)
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>planet</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
</span><span class=literal>'howdy'
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="building_hello_world.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="constructors.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,79 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Extracting C++ objects</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="derived_object_types.html">
<link rel="next" href="enums.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Extracting C++ objects</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="derived_object_types.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="enums.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
At some point, we will need to get C++ values out of object instances. This
can be achieved with the <tt>extract&lt;T&gt;</tt> function. Consider the following:</p>
<code><pre>
<span class=keyword>double </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>o</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;length&quot;</span><span class=special>); </span><span class=comment>// compile error
</span></pre></code>
<p>
In the code above, we got a compiler error because Boost.Python
<tt>object</tt> can't be implicitly converted to <tt>double</tt>s. Instead, what
we wanted to do above can be achieved by writing:</p>
<code><pre>
<span class=keyword>double </span><span class=identifier>l </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=keyword>double</span><span class=special>&gt;(</span><span class=identifier>o</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;length&quot;</span><span class=special>));
</span><span class=identifier>Vec2</span><span class=special>&amp; </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=identifier>Vec2</span><span class=special>&amp;&gt;(</span><span class=identifier>o</span><span class=special>);
</span><span class=identifier>assert</span><span class=special>(</span><span class=identifier>l </span><span class=special>== </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>length</span><span class=special>());
</span></pre></code>
<p>
The first line attempts to extract the &quot;length&quot; attribute of the
Boost.Python <tt>object</tt> <tt>o</tt>. The second line attempts to <i>extract</i> the
<tt>Vec2</tt> object from held by the Boost.Python <tt>object</tt> <tt>o</tt>.</p>
<p>
Take note that we said &quot;attempt to&quot; above. What if the Boost.Python
<tt>object</tt> <tt>o</tt> does not really hold a <tt>Vec2</tt> type? This is certainly
a possibility considering the dynamic nature of Python <tt>object</tt>s. To
be on the safe side, if the C++ type can't be extracted, an
appropriate exception is thrown. To avoid an exception, we need to
test for extractibility:</p>
<code><pre>
<span class=identifier>extract</span><span class=special>&lt;</span><span class=identifier>Vec2</span><span class=special>&amp;&gt; </span><span class=identifier>x</span><span class=special>(</span><span class=identifier>o</span><span class=special>);
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>check</span><span class=special>()) </span><span class=special>{
</span><span class=identifier>Vec2</span><span class=special>&amp; </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>x</span><span class=special>(); </span><span class=special>...
</span></pre></code>
<p>
<img src="theme/bulb.gif"></img> The astute reader might have noticed that the <tt>extract&lt;T&gt;</tt>
facility in fact solves the mutable copying problem:</p>
<code><pre>
<span class=identifier>dict </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=identifier>dict</span><span class=special>&gt;(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>&quot;__dict__&quot;</span><span class=special>));
</span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span><span class=special>= </span><span class=number>3</span><span class=special>; </span>#<span class=identifier>modifies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__ </span><span class=special>!
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="derived_object_types.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="enums.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,73 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Functions</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="class_operators_special_functions.html">
<link rel="next" href="call_policies.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Functions</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_operators_special_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="call_policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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.</p>
<blockquote><p><i>Read on...</i></p></blockquote><p>
But before you do, you might want to fire up Python 2.2 or later and type
<tt>&gt;&gt;&gt; import this</tt>.</p>
<code><pre>
&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 *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</pre></code><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_operators_special_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="call_policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,98 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Inheritance</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="class_properties.html">
<link rel="next" href="class_virtual_functions.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Inheritance</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_properties.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_virtual_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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.</p>
<p>
Consider this trivial inheritance structure:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>Base </span><span class=special>{ </span><span class=keyword>virtual </span><span class=special>~</span><span class=identifier>Base</span><span class=special>(); </span><span class=special>};
</span><span class=keyword>struct </span><span class=identifier>Derived </span><span class=special>: </span><span class=identifier>Base </span><span class=special>{};
</span></pre></code>
<p>
And a set of C++ functions operating on <tt>Base</tt> and <tt>Derived</tt> object
instances:</p>
<code><pre>
<span class=keyword>void </span><span class=identifier>b</span><span class=special>(</span><span class=identifier>Base</span><span class=special>*);
</span><span class=keyword>void </span><span class=identifier>d</span><span class=special>(</span><span class=identifier>Derived</span><span class=special>*);
</span><span class=identifier>Base</span><span class=special>* </span><span class=identifier>factory</span><span class=special>() </span><span class=special>{ </span><span class=keyword>return </span><span class=keyword>new </span><span class=identifier>Derived</span><span class=special>; </span><span class=special>}
</span></pre></code>
<p>
We've seen how we can wrap the base class <tt>Base</tt>:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Base</span><span class=special>&gt;(</span><span class=string>&quot;Base&quot;</span><span class=special>)
</span><span class=comment>/*...*/
</span><span class=special>;
</span></pre></code>
<p>
Now we can inform Boost.Python of the inheritance relationship between
<tt>Derived</tt> and its base class <tt>Base</tt>. Thus:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>Derived</span><span class=special>, </span><span class=identifier>bases</span><span class=special>&lt;</span><span class=identifier>Base</span><span class=special>&gt; </span><span class=special>&gt;(</span><span class=string>&quot;Derived&quot;</span><span class=special>)
</span><span class=comment>/*...*/
</span><span class=special>;
</span></pre></code>
<p>
Doing so, we get some things for free:</p>
<ol><li>Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)</li><li><b>If</b> Base is polymorphic, <tt>Derived</tt> objects which have been passed to Python via a pointer or reference to <tt>Base</tt> can be passed where a pointer or reference to <tt>Derived</tt> is expected.</li></ol><p>
Now, we shall expose the C++ free functions <tt>b</tt> and <tt>d</tt> and <tt>factory</tt>:</p>
<code><pre>
<span class=identifier>def</span><span class=special>(</span><span class=string>&quot;b&quot;</span><span class=special>, </span><span class=identifier>b</span><span class=special>);
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;d&quot;</span><span class=special>, </span><span class=identifier>d</span><span class=special>);
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;factory&quot;</span><span class=special>, </span><span class=identifier>factory</span><span class=special>);
</span></pre></code>
<p>
Note that free function <tt>factory</tt> is being used to generate new
instances of class <tt>Derived</tt>. In such cases, we use
<tt>return_value_policy&lt;manage_new_object&gt;</tt> to instruct Python to adopt
the pointer to <tt>Base</tt> and hold the instance in a new Python <tt>Base</tt>
object until the the Python object is destroyed. We shall see more of
Boost.Python <a href="call_policies.html">
call policies</a> later.</p>
<code><pre>
<span class=comment>// Tell Python to take ownership of factory's result
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;factory&quot;</span><span class=special>, </span><span class=identifier>factory</span><span class=special>,
</span><span class=identifier>return_value_policy</span><span class=special>&lt;</span><span class=identifier>manage_new_object</span><span class=special>&gt;());
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="class_properties.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="class_virtual_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,101 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Iterators</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="enums.html">
<link rel="next" href="exception_translation.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Iterators</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="enums.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exception_translation.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
In C++, and STL in particular, we see iterators everywhere. Python also has
iterators, but these are two very different beasts.</p>
<p>
<b>C++ iterators:</b></p>
<ul><li>C++ has 5 type categories (random-access, bidirectional, forward, input, output)</li><li>There are 2 Operation categories: reposition, access</li><li>A pair of iterators is needed to represent a (first/last) range.</li></ul><p>
<b>Python Iterators:</b></p>
<ul><li>1 category (forward)</li><li>1 operation category (next())</li><li>Raises StopIteration exception at end</li></ul><p>
The typical Python iteration protocol: <tt><b>for y in x...</b></tt> is as follows:</p>
<code><pre>
<span class=identifier>iter </span><span class=special>= </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__iter__</span><span class=special>() </span>#<span class=identifier>get </span><span class=identifier>iterator
</span><span class=keyword>try</span><span class=special>:
</span><span class=keyword>while </span><span class=number>1</span><span class=special>:
</span><span class=identifier>y </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>() </span>#<span class=identifier>get </span><span class=identifier>each </span><span class=identifier>item
</span><span class=special>... </span>#<span class=identifier>process </span><span class=identifier>y
</span><span class=identifier>except </span><span class=identifier>StopIteration</span><span class=special>: </span><span class=identifier>pass </span>#<span class=identifier>iterator </span><span class=identifier>exhausted
</span></pre></code>
<p>
Boost.Python provides some mechanisms to make C++ iterators play along
nicely as Python iterators. What we need to do is to produce
appropriate __iter__ function from C++ iterators that is compatible
with the Python iteration protocol. For example:</p>
<code><pre>
<span class=identifier>object </span><span class=identifier>get_iterator </span><span class=special>= </span><span class=identifier>iterator</span><span class=special>&lt;</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt; </span><span class=special>&gt;();
</span><span class=identifier>object </span><span class=identifier>iter </span><span class=special>= </span><span class=identifier>get_iterator</span><span class=special>(</span><span class=identifier>v</span><span class=special>);
</span><span class=identifier>object </span><span class=identifier>first </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>();
</span></pre></code>
<p>
Or for use in class_&lt;&gt;:</p>
<code><pre>
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;__iter__&quot;</span><span class=special>, </span><span class=identifier>iterator</span><span class=special>&lt;</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt; </span><span class=special>&gt;())
</span></pre></code>
<p>
<b>range</b></p>
<p>
We can create a Python savvy iterator using the range function:</p>
<ul><li>range(start, finish)</li><li>range&lt;Policies,Target&gt;(start, finish)</li></ul><p>
Here, start/finish may be one of:</p>
<ul><li>member data pointers</li><li>member function pointers</li><li>adaptable function object (use Target parameter)</li></ul><p>
<b>iterator</b></p>
<ul><li>iterator&lt;T, Policies&gt;()</li></ul><p>
Given a container <tt>T</tt>, iterator is a shortcut that simply calls <tt>range</tt>
with &amp;T::begin, &amp;T::end.</p>
<p>
Let's put this into action... Here's an example from some hypothetical
bogon Particle accelerator code:</p>
<code><pre>
<span class=identifier>f </span><span class=special>= </span><span class=identifier>Field</span><span class=special>()
</span><span class=keyword>for </span><span class=identifier>x </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>pions</span><span class=special>:
</span><span class=identifier>smash</span><span class=special>(</span><span class=identifier>x</span><span class=special>)
</span><span class=keyword>for </span><span class=identifier>y </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>bogons</span><span class=special>:
</span><span class=identifier>count</span><span class=special>(</span><span class=identifier>y</span><span class=special>)
</span></pre></code>
<p>
Now, our C++ Wrapper:</p>
<code><pre>
<span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>F</span><span class=special>&gt;(</span><span class=string>&quot;Field&quot;</span><span class=special>)
</span><span class=special>.</span><span class=identifier>property</span><span class=special>(</span><span class=string>&quot;pions&quot;</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&amp;</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_begin</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_end</span><span class=special>))
</span><span class=special>.</span><span class=identifier>property</span><span class=special>(</span><span class=string>&quot;bogons&quot;</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&amp;</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_begin</span><span class=special>, </span><span class=special>&amp;</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_end</span><span class=special>));
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="enums.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exception_translation.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,54 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Object Interface</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="default_arguments.html">
<link rel="next" href="basic_interface.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Object Interface</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="default_arguments.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="basic_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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 <tt>object</tt>. We shall see in
this chapter how to deal with Python objects.</p>
<p>
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++ <tt>object</tt>s are as close as possible to Python. This
should minimize the learning curve significantly.</p>
<p>
<img src="theme/python.png"></img></p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="default_arguments.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="basic_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,79 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>QuickStart</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="next" href="building_hello_world.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>QuickStart</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="building_hello_world.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
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).</p>
<a name="hello_world"></a><h2>Hello World</h2><p>
Following C/C++ tradition, let's start with the &quot;hello, world&quot;. A C++
Function:</p>
<code><pre>
<span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>greet</span><span class=special>()
</span><span class=special>{
</span><span class=keyword>return </span><span class=string>&quot;hello, world&quot;</span><span class=special>;
</span><span class=special>}
</span></pre></code>
<p>
can be exposed to Python by writing a Boost.Python wrapper:</p>
<code><pre>
<span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
</span><span class=special>{
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;greet&quot;</span><span class=special>, </span><span class=identifier>greet</span><span class=special>);
</span><span class=special>}
</span></pre></code>
<p>
That's it. We're done. We can now build this as a shared library. The
resulting DLL is now visible to Python. Here's a sample Python session:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
</span><span class=identifier>hello</span><span class=special>, </span><span class=identifier>world
</span></pre></code>
<blockquote><p><i><b>Next stop... Building your Hello World module from start to finish...</b></i></p></blockquote><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="building_hello_world.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1 +0,0 @@
‰PNG

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

View File

@@ -1 +0,0 @@
‰PNG

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

View File

@@ -1,170 +0,0 @@
body
{
background-image: url(bkd.gif);
background-color: #FFFFFF;
margin: 1em 2em 1em 2em;
}
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; text-align: left; }
h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
pre
{
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-top: 2pt;
padding-right: 2pt;
padding-left: 2pt;
padding-bottom: 2pt;
display: block;
font-family: "courier new", courier, mono;
background-color: #eeeeee; font-size: small
}
code
{
font-family: "Courier New", Courier, mono;
font-size: small
}
tt
{
display: inline;
font-family: "Courier New", Courier, mono;
color: #000099;
font-size: small
}
p
{
text-align: justify;
font-family: Georgia, "Times New Roman", Times, serif
}
ul
{
list-style-image: url(bullet.gif);
font-family: Georgia, "Times New Roman", Times, serif
}
ol
{
font-family: Georgia, "Times New Roman", Times, serif
}
a
{
font-weight: bold;
color: #003366;
text-decoration: none;
}
a:hover { color: #8080FF; }
.literal { color: #666666; font-style: italic}
.keyword { color: #000099}
.identifier {}
.comment { font-style: italic; color: #990000}
.special { color: #800040}
.preprocessor { color: #FF0000}
.string { font-style: italic; color: #666666}
.copyright { color: #666666; font-size: small}
.white_bkd { background-color: #FFFFFF}
.dk_grey_bkd { background-color: #999999}
.quotes { color: #666666; font-style: italic; font-weight: bold}
.note_box
{
display: block;
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-right: 12pt;
padding-left: 12pt;
padding-bottom: 12pt;
padding-top: 12pt;
font-family: Arial, Helvetica, sans-serif;
background-color: #E2E9EF;
font-size: small; text-align: justify
}
.table_title
{
background-color: #648CCA;
font-family: Verdana, Arial, Helvetica, sans-serif; color: #FFFFFF;
font-weight: bold
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.table_cells
{
background-color: #E2E9EF;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.toc
{
DISPLAY: block;
background-color: #E2E9EF
font-family: Arial, Helvetica, sans-serif;
border-top: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
border-right: gray 1pt solid;
padding-top: 24pt;
padding-right: 24pt;
padding-left: 24pt;
padding-bottom: 24pt;
}
.toc_title
{
background-color: #648CCA;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
color: #FFFFFF;
font-weight: bold
}
.toc_cells
{
background-color: #E2E9EF;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
}
div.logo
{
float: right;
}
.toc_cells_L0 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L1 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 44px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L2 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 88px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L3 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 122px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L4 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 166px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

View File

@@ -1,184 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Using the interpreter</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="embedding.html">
</head>
<body>
<table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
<tr>
<td width="10">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Using the interpreter</b></font>
</td>
<td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" align="right" border="0"></a></td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<p>
As you probably already know, objects in Python are reference-counted. Naturally, the <tt>PyObject</tt>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 <a href="http://www.python.org/doc/current/api/refcounts.html">
by hand</a>. This is messy and especially hard to get right in the presence of C++ exceptions. Fortunately Boost.Python provides the <a href="../../v2/handle.html">
handle</a> class template to automate the process.</p>
<a name="reference_counting_handles"></a><h2>Reference-counting handles</h2><p>
There are two ways in which a function in the Python/C API can return a <tt>PyObject*</tt>: as a <i>borrowed reference</i> or as a <i>new reference</i>. 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.</p>
<p>
For a function returning a <i>borrowed reference</i> we'll have to tell the <tt>handle</tt> that the <tt>PyObject*</tt> is borrowed with the aptly named <a href="../../v2/handle.html#borrowed-spec">
borrowed</a> function. Two functions returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125">
PyImport_AddModule</a> and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594">
PyModule_GetDict</a>. 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 <tt>__main__</tt> module:</p>
<code><pre>
<span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>) </span><span class=special>));
</span><span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_namespace</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) </span><span class=special>));
</span></pre></code>
<p>
Because the Python/C API doesn't know anything about <tt>handle</tt>s, we used the <a href="../../v2/handle.html#handle-spec-observers">
get</a> member function to retrieve the <tt>PyObject*</tt> from which the <tt>handle</tt> was constructed.</p>
<p>
For a function returning a <i>new reference</i> we can just create a <tt>handle</tt> out of the raw <tt>PyObject*</tt> without wrapping it in a call to borrowed. One such function that returns a new reference is <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> which we'll discuss in the next section.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/lens.gif"></img> <b>Handle is a class <i>template</i>, so why haven't we been using any template parameters?</b><br>
<br>
<tt>handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt>PyObject</tt> 99% of the time, so the parameter was defaulted to <tt>PyObject</tt> for convenience. Therefore we can use the shorthand <tt>handle&lt;&gt;</tt> instead of the longer, but equivalent, <tt>handle&lt;PyObject&gt;</tt>.
</td>
</tr>
</table>
<a name="running_python_code"></a><h2>Running Python code</h2><p>
To run Python code from C++ there is a family of functions in the API starting with the PyRun prefix. You can find the full list of these functions <a href="http://www.python.org/doc/current/api/veryhigh.html">
here</a>. They all work similarly so we will look at only one of them, namely:</p>
<code><pre>
<span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=keyword>char </span><span class=special>*</span><span class=identifier>str</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>start</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>globals</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>locals</span><span class=special>)
</span></pre></code>
<p>
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> takes the code to execute as a null-terminated (C-style) string in its <tt>str</tt> parameter. The function returns a new reference to a Python object. Which object is returned depends on the <tt>start</tt> paramater.</p>
<p>
The <tt>start</tt> parameter is the start symbol from the Python grammar to use for interpreting the code. The possible values are:</p>
<table width="90%" border="0" align="center"> <tr>
<td class="table_title" colspan="6">
Start symbols </td>
</tr>
<tr><tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
Py_eval_input</a></td><td class="table_cells">for interpreting isolated expressions</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
Py_file_input</a></td><td class="table_cells">for interpreting sequences of statements</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">
Py_single_input</a></td><td class="table_cells">for interpreting a single statement</td></tr></table>
<p>
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
Py_eval_input</a>, the input string must contain a single expression and its result is returned. When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
Py_file_input</a>, the string can contain an abitrary number of statements and None is returned. <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">
Py_single_input</a> works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
Py_file_input</a> but only accepts a single statement.</p>
<p>
Lastly, the <tt>globals</tt> and <tt>locals</tt> 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 <tt>__main__</tt> module for both parameters.</p>
<p>
We have already seen how to get the <tt>__main__</tt> module's namespace so let's run some Python code in it: </p>
<code><pre>
<span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>) </span><span class=special>));
</span><span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_namespace</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) </span><span class=special>));
</span><span class=identifier>handle</span><span class=special>&lt;&gt;( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;hello = file('hello.txt', 'w')\n&quot;
</span><span class=string>&quot;hello.write('Hello world!')\n&quot;
</span><span class=string>&quot;hello.close()&quot;</span><span class=special>, </span><span class=identifier>Py_file_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>get</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) </span><span class=special>);
</span></pre></code>
<p>
This should create a file called 'hello.txt' in the current directory containing a phrase that is well-known in programming circles. </p>
<p>
<img src="theme/note.gif"></img> <b>Note</b> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> in a (nameless) <tt>handle</tt> even though we are not interested in it. If we didn't do this, the the returned object would be kept alive unnecessarily. Unless you want to be a Dr. Frankenstein, always wrap <tt>PyObject*</tt>s in <tt>handle</tt>s.</p>
<a name="beyond_handles"></a><h2>Beyond handles</h2><p>
It's nice that <tt>handle</tt> manages the reference counting details for us, but other than that it doesn't do much. Often we'd like to have a more useful class to manipulate Python objects. But we have already seen such a class in the <a href="object_interface.html">
previous section</a>: the aptly named <tt>object</tt> class and it's derivatives. What we haven't seen, is that they can be constructed from a <tt>handle</tt>. The following examples should illustrate this fact:</p>
<code><pre>
<span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>) </span><span class=special>));
</span><span class=identifier>main_namespace </span><span class=identifier>dict</span><span class=special>(</span><span class=identifier>handle</span><span class=special>&lt;&gt;(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) </span><span class=special>)));
</span><span class=identifier>handle</span><span class=special>&lt;&gt;( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;result = 5 ** 2&quot;</span><span class=special>, </span><span class=identifier>Py_file_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) </span><span class=special>);
</span><span class=keyword>int </span><span class=identifier>five_squared </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;( </span><span class=identifier>main_namespace</span><span class=special>[</span><span class=string>&quot;result&quot;</span><span class=special>] </span><span class=special>);
</span></pre></code>
<p>
Here we create a dictionary object for the <tt>__main__</tt> 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 <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
Py_eval_input</a>:</p>
<code><pre>
<span class=identifier>object </span><span class=identifier>result</span><span class=special>(</span><span class=identifier>handle</span><span class=special>&lt;&gt;( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;5 ** 2&quot;</span><span class=special>, </span><span class=identifier>Py_eval_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) </span><span class=special>));
</span><span class=keyword>int </span><span class=identifier>five_squared </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>result</span><span class=special>);
</span></pre></code>
<p>
<img src="theme/note.gif"></img> <b>Note</b> that <tt>object</tt>'s member function to return the wrapped <tt>PyObject*</tt> is called <tt>ptr</tt> instead of <tt>get</tt>. This makes sense if you take into account the different functions that <tt>object</tt> and <tt>handle</tt> perform.</p>
<a name="exception_handling"></a><h2>Exception handling</h2><p>
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
PyRun_String</a> function returns a null pointer. Constructing a <tt>handle</tt> out of this null pointer throws <a href="../../v2/errors.html#error_already_set-spec">
error_already_set</a>, so basically, the Python exception is automatically translated into a C++ exception when using <tt>handle</tt>:</p>
<code><pre>
<span class=keyword>try
</span><span class=special>{
</span><span class=identifier>object </span><span class=identifier>result</span><span class=special>(</span><span class=identifier>handle</span><span class=special>&lt;&gt;( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;5/0&quot;</span><span class=special>, </span><span class=identifier>Py_eval_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) </span><span class=special>));
</span><span class=comment>// execution will never get here:
</span><span class=keyword>int </span><span class=identifier>five_divided_by_zero </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>result</span><span class=special>);
</span><span class=special>}
</span><span class=keyword>catch</span><span class=special>(</span><span class=identifier>error_already_set</span><span class=special>)
</span><span class=special>{
</span><span class=comment>// handle the exception in some way
</span><span class=special>}
</span></pre></code>
<p>
The <tt>error_already_set</tt> exception class doesn't carry any information in itself. To find out more about the Python exception that occurred, you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html">
exception handling functions</a> of the Python/C API in your catch-statement. This can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70">
PyErr_Print()</a> to print the exception's traceback to the console, or comparing the type of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html">
standard exceptions</a>:</p>
<code><pre>
<span class=keyword>catch</span><span class=special>(</span><span class=identifier>error_already_set</span><span class=special>)
</span><span class=special>{
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>PyErr_ExceptionMatches</span><span class=special>(</span><span class=identifier>PyExc_ZeroDivisionError</span><span class=special>))
</span><span class=special>{
</span><span class=comment>// handle ZeroDivisionError specially
</span><span class=special>}
</span><span class=keyword>else
</span><span class=special>{
</span><span class=comment>// print all other errors to stderr
</span><span class=identifier>PyErr_Print</span><span class=special>();
</span><span class=special>}
</span><span class=special>}
</span></pre></code>
<p>
(To retrieve even more information from the exception you can use some of the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html">
here</a>.)</p>
<p>
If you'd rather not have <tt>handle</tt> throw a C++ exception when it is constructed, you can use the <a href="../../v2/handle.html#allow_null-spec">
allow_null</a> function in the same way you'd use borrowed:</p>
<code><pre>
<span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>result</span><span class=special>(</span><span class=identifier>allow_null</span><span class=special>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;5/0&quot;</span><span class=special>, </span><span class=identifier>Py_eval_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) </span><span class=special>));
</span><span class=keyword>if </span><span class=special>(!</span><span class=identifier>result</span><span class=special>)
</span><span class=comment>// Python exception occurred
</span><span class=keyword>else
</span><span class=comment>// everything went okay, it's safe to use the result
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 Dirk Gerrits <br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,126 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Boost Python Tutorial</title>
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
<link rel="next" href="quickstart.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="doc/theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Boost Python Tutorial</b></font>
</td>
</tr>
</table>
<br>
<table width="80%" border="0" align="center">
<tr>
<td class="toc_title">Table of contents</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/quickstart.html">QuickStart</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/building_hello_world.html">Building Hello World</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/exposing_classes.html">Exposing Classes</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/constructors.html">Constructors</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/class_data_members.html">Class Data Members</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/class_properties.html">Class Properties</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/inheritance.html">Inheritance</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/class_virtual_functions.html">Class Virtual Functions</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/class_operators_special_functions.html">Class Operators/Special Functions</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/functions.html">Functions</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/call_policies.html">Call Policies</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/default_arguments.html">Default Arguments</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/object_interface.html">Object Interface</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/basic_interface.html">Basic Interface</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/derived_object_types.html">Derived Object types</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/extracting_c___objects.html">Extracting C++ objects</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/enums.html">Enums</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/iterators.html">Iterators</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/exception_translation.html">Exception Translation</a>
</td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002 David Abrahams<br>Copyright &copy; 2002 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>