mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Enhance embedding python docs.
[SVN r37710]
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter 1. python 1.0</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||
<link rel="next" href="python/hello.html" title="Building Hello World">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -34,7 +31,7 @@
|
||||
<div><p class="copyright">Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id376848"></a><p>
|
||||
<a name="id3128483"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
@@ -96,10 +93,10 @@
|
||||
code takes on the look of a kind of declarative interface definition language
|
||||
(IDL).
|
||||
</p>
|
||||
<a name="quickstart.hello_world"></a><h2>
|
||||
<a name="id447173"></a>
|
||||
<a name="quickstart.hello_world"></a><h3>
|
||||
<a name="id3090903"></a>
|
||||
Hello World
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A
|
||||
C++ Function:
|
||||
@@ -136,13 +133,13 @@
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module
|
||||
from start to finish...</b></span></em></span>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Next stop... Building your Hello World module
|
||||
from start to finish...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><small><p>Last revised: August 31, 2006 at 05:59:58 GMT</p></small></td>
|
||||
<td align="left"><small><p>Last revised: May 18, 2007 at 15:45:45 GMT</p></small></td>
|
||||
<td align="right"><small></small></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Embedding</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="object.html" title=" Object Interface">
|
||||
<link rel="prev" href="object.html" title="Object Interface">
|
||||
<link rel="next" href="iterators.html" title="Iterators">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -42,30 +39,28 @@
|
||||
a lot easier and, in a future version, it may become unnecessary to touch the
|
||||
Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
|
||||
</p>
|
||||
<a name="embedding.building_embedded_programs"></a><h2>
|
||||
<a name="id462650"></a>
|
||||
<a name="embedding.building_embedded_programs"></a><h3>
|
||||
<a name="id3150903"></a>
|
||||
Building embedded programs
|
||||
</h2>
|
||||
</h3>
|
||||
<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.
|
||||
To be able to embed python into your programs, you have to link to both Boost.Python's
|
||||
as well as Python's own runtime library.
|
||||
</p>
|
||||
<p>
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On
|
||||
Windows, the variants are called <tt class="literal">boost_python.lib</tt> (for release
|
||||
builds) and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you
|
||||
can't find the libraries, you probably haven't built Boost.Python yet. See
|
||||
<a href="../../../../building.html" target="_top">Building and Testing</a> on how to
|
||||
do this.
|
||||
Boost.Python's library comes in two variants. Both are located in Boost's
|
||||
<code class="literal">/libs/python/build/bin-stage</code> subdirectory. On Windows, the
|
||||
variants are called <code class="literal">boost_python.lib</code> (for release builds)
|
||||
and <code class="literal">boost_python_debug.lib</code> (for debugging). If you can't
|
||||
find the libraries, you probably haven't built Boost.Python yet. See <a href="../../../../building.html" target="_top">Building and Testing</a> on how to do this.
|
||||
</p>
|
||||
<p>
|
||||
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory
|
||||
Python's library can be found in the <code class="literal">/libs</code> 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 class="literal">/include</tt> subdirectory has to be added
|
||||
Additionally, Python's <code class="literal">/include</code> subdirectory has to be added
|
||||
to your include path.
|
||||
</p>
|
||||
<p>
|
||||
@@ -86,44 +81,49 @@ exe embedded_program # name of the executable
|
||||
<library-path>$(PYTHON_LIB_PATH)
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
</pre>
|
||||
<a name="embedding.getting_started"></a><h2>
|
||||
<a name="id462747"></a>
|
||||
<a name="embedding.getting_started"></a><h3>
|
||||
<a name="id3150996"></a>
|
||||
Getting started
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Being able to build is nice, but there is nothing to build yet. Embedding the
|
||||
Python interpreter into one of your C++ programs requires these 4 steps:
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
#include <tt class="literal"><boost/python.hpp></tt><br><br>
|
||||
|
||||
#include
|
||||
<code class="literal"><boost/python.hpp></code><br><br>
|
||||
</li>
|
||||
<li>
|
||||
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
|
||||
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
to start the interpreter and create the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
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" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter and release its resources.
|
||||
</li>
|
||||
</ol></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Note that at this time
|
||||
you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter. This may be fixed in a future version of boost.python.</strong></span>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</b></span></em></span>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||
<p>
|
||||
As you probably already know, objects in Python are reference-counted. Naturally,
|
||||
the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted.
|
||||
the <code class="literal">PyObject</code>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" target="_top">by
|
||||
hand</a>. This is messy and especially hard to get right in the presence
|
||||
@@ -131,240 +131,106 @@ exe embedded_program # name of the executable
|
||||
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
|
||||
automate the process.
|
||||
</p>
|
||||
<a name="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
|
||||
<a name="id462914"></a>
|
||||
Reference-counting handles and objects
|
||||
</h2>
|
||||
<p>
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span>
|
||||
or as a <span class="emphasis"><em>new reference</em></span>. Which of 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 <span class="emphasis"><em>borrowed reference</em></span> we'll
|
||||
have to tell the <tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt>
|
||||
is borrowed with the aptly named <a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a>
|
||||
function. Two functions returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a>
|
||||
and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594" target="_top">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 class="literal"><span class="underline">_main</span>_</tt>
|
||||
module:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
For a function returning a <span class="emphasis"><em>new reference</em></span> we can just
|
||||
create a <tt class="literal">handle</tt> out of the raw <tt class="literal">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" target="_top">PyRun_String</a>
|
||||
which we'll discuss in the next section.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>,
|
||||
so why haven't we been using any template parameters?</b></span><br> <br>
|
||||
<tt class="literal">handle</tt> has a single template parameter specifying the
|
||||
type of the managed object. This type is <tt class="literal">PyObject</tt> 99%
|
||||
of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt>
|
||||
for convenience. Therefore we can use the shorthand <tt class="literal">handle<></tt>
|
||||
instead of the longer, but equivalent, <tt class="literal">handle<PyObject></tt>.
|
||||
</p>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||
<a name="id463241"></a>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h3>
|
||||
<a name="id3151190"></a>
|
||||
Running Python code
|
||||
</h2>
|
||||
</h3>
|
||||
<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" target="_top">here</a>. They
|
||||
all work similarly so we will look at only one of them, namely:
|
||||
Boost.python provides three related functions to run Python code from C++.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">PyObject</span><span class="special">*</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><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>
|
||||
<span class="identifier">object</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">expression</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
<span class="identifier">object</span> <span class="identifier">exec</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">code</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
<span class="identifier">object</span> <span class="identifier">exec_file</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">filename</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">globals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">(),</span> <span class="identifier">object</span> <span class="identifier">locals</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">())</span>
|
||||
</pre>
|
||||
<p>
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
takes the code to execute as a null-terminated (C-style) string in its <tt class="literal">str</tt>
|
||||
parameter. The function returns a new reference to a Python object. Which
|
||||
object is returned depends on the <tt class="literal">start</tt> paramater.
|
||||
eval evaluates the given expression and returns the resulting value. exec
|
||||
executes the given code (typically a set of statements) returning the result,
|
||||
and exec_file executes the code contained in the given file.
|
||||
</p>
|
||||
<p>
|
||||
The <tt class="literal">start</tt> parameter is the start symbol from the Python
|
||||
grammar to use for interpreting the code. The possible values are:
|
||||
</p>
|
||||
<div class="informaltable">
|
||||
<h4>
|
||||
<a name="id463420"></a>
|
||||
<span class="table-title">Start symbols</span>
|
||||
</h4>
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a></th>
|
||||
<th>for
|
||||
interpreting isolated expressions</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a></td>
|
||||
<td>for
|
||||
interpreting sequences of statements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a></td>
|
||||
<td>for
|
||||
interpreting a single statement</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">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" target="_top">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" target="_top">Py_single_input</a>
|
||||
works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
but only accepts a single statement.
|
||||
</p>
|
||||
<p>
|
||||
Lastly, the <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters
|
||||
are Python dictionaries containing the globals and locals of the context
|
||||
in which to run the code. For most intents and purposes you can use the namespace
|
||||
dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
The <code class="literal">globals</code> and <code class="literal">locals</code> 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 <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module for both parameters.
|
||||
</p>
|
||||
<p>
|
||||
We have already seen how to get the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module's namespace so let's run some Python code in it:
|
||||
Boost.python provides a function to import a module:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
|
||||
<span class="string">"hello = file('hello.txt', 'w')\n"</span>
|
||||
<span class="string">"hello.write('Hello world!')\n"</span>
|
||||
<span class="string">"hello.close()"</span>
|
||||
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
<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="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||
<span class="special">));</span>
|
||||
<span class="identifier">object</span> <span class="identifier">import</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s,
|
||||
we used the object's <tt class="literal">ptr</tt> member function to retrieve the
|
||||
<tt class="literal">PyObject*</tt>.
|
||||
import imports a python module (potentially loading it into the running process
|
||||
first), and returns it.
|
||||
</p>
|
||||
<p>
|
||||
Let's import the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module and run some Python code in its namespace:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"hello = file('hello.txt', 'w')\n"</span>
|
||||
<span class="string">"hello.write('Hello world!')\n"</span>
|
||||
<span class="string">"hello.close()"</span><span class="special">,</span>
|
||||
<span class="identifier">main_namespace</span><span class="special">);</span>
|
||||
</pre>
|
||||
<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 class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Note</b></span> that we wrap
|
||||
the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
in a (nameless) <tt class="literal">handle</tt> even though we are not interested
|
||||
in it. If we didn't do this, the the returned object would be kept alive
|
||||
unnecessarily. Unless you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s
|
||||
in <tt class="literal">handle</tt>s.
|
||||
</p>
|
||||
<a name="using_the_interpreter.beyond_handles"></a><h2>
|
||||
<a name="id463926"></a>
|
||||
Beyond handles
|
||||
</h2>
|
||||
<a name="using_the_interpreter.manipulating_python_objects"></a><h3>
|
||||
<a name="id3151717"></a>
|
||||
Manipulating Python objects
|
||||
</h3>
|
||||
<p>
|
||||
It's nice that <tt class="literal">handle</tt> manages the reference counting details
|
||||
for us, but other than that it doesn't do much. Often we'd like to have a
|
||||
more useful class to manipulate Python objects. But we have already seen
|
||||
such a class above, and in the <a href="object.html" target="_top">previous section</a>:
|
||||
the aptly named <tt class="literal">object</tt> class and it's derivatives. We've
|
||||
already seen that they can be constructed from a <tt class="literal">handle</tt>.
|
||||
Often we'd like to have a class to manipulate Python objects. But we have
|
||||
already seen such a class above, and in the <a href="object.html" target="_top">previous
|
||||
section</a>: the aptly named <code class="literal">object</code> class and its
|
||||
derivatives. We've already seen that they can be constructed from a <code class="literal">handle</code>.
|
||||
The following examples should further illustrate this fact:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">main_module</span> <span class="special">=</span> <span class="identifier">import</span><span class="special">(</span><span class="string">"__main__"</span><span class="special">);</span>
|
||||
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
|
||||
<span class="string">"result = 5 ** 2"</span>
|
||||
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||
<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="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">ignored</span> <span class="special">=</span> <span class="identifier">exec</span><span class="special">(</span><span class="string">"result = 5 ** 2"</span><span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">);</span>
|
||||
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
Here we create a dictionary object for the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
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" target="_top">PyRun_String</a>
|
||||
return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>:
|
||||
is to use eval instead, which returns the result directly:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span>
|
||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">"5 ** 2"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<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="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</span><span class="special">);</span>
|
||||
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s
|
||||
member function to return the wrapped <tt class="literal">PyObject*</tt> is called
|
||||
<tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense
|
||||
if you take into account the different functions that <tt class="literal">object</tt>
|
||||
and <tt class="literal">handle</tt> perform.
|
||||
</p>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||
<a name="id464549"></a>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h3>
|
||||
<a name="id3152050"></a>
|
||||
Exception handling
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||
function returns a null pointer. Constructing a <tt class="literal">handle</tt>
|
||||
out of this null pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||
so basically, the Python exception is automatically translated into a C++
|
||||
exception when using <tt class="literal">handle</tt>:
|
||||
If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>
|
||||
is thrown:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<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"><>(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
<span class="string">"5/0"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<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="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||
<span class="special">));</span>
|
||||
|
||||
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5/0"</span><span class="special">);</span>
|
||||
<span class="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"><</span><span class="keyword">int</span><span class="special">>(</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="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</span> <span class="special">&)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// handle the exception in some way
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
|
||||
The <code class="literal">error_already_set</code> 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" target="_top">exception
|
||||
handling functions</a> of the Python/C API in your catch-statement. This
|
||||
@@ -374,7 +240,7 @@ exe embedded_program # name of the executable
|
||||
exceptions</a>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
|
||||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span> <span class="keyword">const</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>
|
||||
@@ -391,23 +257,6 @@ exe embedded_program # name of the executable
|
||||
(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" target="_top">here</a>.)
|
||||
</p>
|
||||
<p>
|
||||
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception
|
||||
when it is constructed, you can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a>
|
||||
function in the same way you'd use borrowed:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||
<span class="string">"5/0"</span>
|
||||
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||
<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="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</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>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exception Translation</title>
|
||||
<title>Exception Translation</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="iterators.html" title="Iterators">
|
||||
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||
<link rel="next" href="techniques.html" title="General Techniques">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Exposing Classes</title>
|
||||
<title>Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="hello.html" title=" Building Hello World">
|
||||
<link rel="prev" href="hello.html" title="Building Hello World">
|
||||
<link rel="next" href="functions.html" title="Functions">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -67,9 +64,9 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
|
||||
and <tt class="literal">set</tt>. Now, after building our module as a shared library,
|
||||
we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <code class="literal">greet</code>
|
||||
and <code class="literal">set</code>. Now, after building our module as a shared library,
|
||||
we may use our class <code class="literal">World</code> in Python. Here's a sample Python
|
||||
session:
|
||||
</p>
|
||||
<p>
|
||||
@@ -85,7 +82,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||
<p>
|
||||
Our previous example didn't have any explicit constructors. Since <tt class="literal">World</tt>
|
||||
Our previous example didn't have any explicit constructors. Since <code class="literal">World</code>
|
||||
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
|
||||
@@ -109,9 +106,9 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
This time <tt class="literal">World</tt> has no default constructor; our previous
|
||||
This time <code class="literal">World</code> 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="literal">class_<World></tt> about the constructor
|
||||
We have to tell <code class="literal">class_<World></code> about the constructor
|
||||
we want to expose instead.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -127,13 +124,13 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="literal">init<std::string>()</tt> exposes the constructor taking
|
||||
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
|
||||
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
|
||||
<code class="literal">init<std::string>()</code> exposes the constructor taking
|
||||
in a <code class="literal">std::string</code> (in Python, constructors are spelled
|
||||
"<code class="literal">"<span class="underline">_init</span>_"</code>").
|
||||
</p>
|
||||
<p>
|
||||
We can expose additional constructors by passing more <tt class="literal">init<...></tt>s
|
||||
to the <tt class="literal">def()</tt> member function. Say for example we have
|
||||
We can expose additional constructors by passing more <code class="literal">init<...></code>s
|
||||
to the <code class="literal">def()</code> member function. Say for example we have
|
||||
another World constructor taking in two doubles:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -145,13 +142,13 @@
|
||||
</pre>
|
||||
<p>
|
||||
On the other hand, if we do not wish to expose any constructors at all, we
|
||||
may use <tt class="literal">no_init</tt> instead:
|
||||
may use <code class="literal">no_init</code> instead:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
|
||||
This actually adds an <code class="literal"><span class="underline">_init</span>_</code>
|
||||
method which always raises a Python RuntimeError exception.
|
||||
</p>
|
||||
</div>
|
||||
@@ -161,8 +158,8 @@
|
||||
<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 <span class="bold"><b>read-only</b></span>
|
||||
or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
|
||||
to be exposed may be regarded as <span class="bold"><strong>read-only</strong></span>
|
||||
or <span class="bold"><strong>read-write</strong></span>. Consider this class <code class="literal">Var</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Var</span>
|
||||
@@ -173,7 +170,7 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
|
||||
Our C++ <code class="literal">Var</code> class and its data members can be exposed
|
||||
to Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -194,8 +191,8 @@
|
||||
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
|
||||
while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
|
||||
Note that <code class="literal">name</code> is exposed as <span class="bold"><strong>read-only</strong></span>
|
||||
while <code class="literal">value</code> is exposed as <span class="bold"><strong>read-write</strong></span>.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
|
||||
@@ -227,7 +224,7 @@
|
||||
<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 class="literal">Num</tt>
|
||||
can just be a different syntax for a method call. Wrapping our <code class="literal">Num</code>
|
||||
class using Boost.Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -248,8 +245,8 @@
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
|
||||
</span></pre>
|
||||
<p>
|
||||
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
|
||||
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
|
||||
Take note that the class property <code class="literal">rovalue</code> is exposed as
|
||||
<span class="bold"><strong>read-only</strong></span> since the <code class="literal">rovalue</code>
|
||||
setter member function is not passed in:
|
||||
</p>
|
||||
<p>
|
||||
@@ -276,7 +273,7 @@
|
||||
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
|
||||
</pre>
|
||||
<p>
|
||||
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
|
||||
And a set of C++ functions operating on <code class="literal">Base</code> and <code class="literal">Derived</code>
|
||||
object instances:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -285,7 +282,7 @@
|
||||
<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>
|
||||
<p>
|
||||
We've seen how we can wrap the base class <tt class="literal">Base</tt>:
|
||||
We've seen how we can wrap the base class <code class="literal">Base</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -293,8 +290,8 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
|
||||
and its base class <tt class="literal">Base</tt>. Thus:
|
||||
Now we can inform Boost.Python of the inheritance relationship between <code class="literal">Derived</code>
|
||||
and its base class <code class="literal">Base</code>. Thus:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</span><span class="string">"Derived"</span><span class="special">)</span>
|
||||
@@ -310,15 +307,15 @@
|
||||
member functions)
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
|
||||
<span class="bold"><strong>If</strong></span> Base is polymorphic, <code class="literal">Derived</code>
|
||||
objects which have been passed to Python via a pointer or reference to
|
||||
<tt class="literal">Base</tt> can be passed where a pointer or reference to
|
||||
<tt class="literal">Derived</tt> is expected.
|
||||
<code class="literal">Base</code> can be passed where a pointer or reference to
|
||||
<code class="literal">Derived</code> is expected.
|
||||
</li>
|
||||
</ol></div>
|
||||
<p>
|
||||
Now, we shall expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
|
||||
and <tt class="literal">factory</tt>:
|
||||
Now, we shall expose the C++ free functions <code class="literal">b</code> and <code class="literal">d</code>
|
||||
and <code class="literal">factory</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
|
||||
@@ -326,11 +323,11 @@
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that free function <tt class="literal">factory</tt> is being used to generate
|
||||
new instances of class <tt class="literal">Derived</tt>. In such cases, we use
|
||||
<tt class="literal">return_value_policy<manage_new_object></tt> to instruct
|
||||
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
|
||||
in a new Python <tt class="literal">Base</tt> object until the the Python object
|
||||
Note that free function <code class="literal">factory</code> is being used to generate
|
||||
new instances of class <code class="literal">Derived</code>. In such cases, we use
|
||||
<code class="literal">return_value_policy<manage_new_object></code> to instruct
|
||||
Python to adopt the pointer to <code class="literal">Base</code> and hold the instance
|
||||
in a new Python <code class="literal">Base</code> object until the the Python object
|
||||
is destroyed. We shall see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
|
||||
policies</a> later.
|
||||
</p>
|
||||
@@ -346,7 +343,7 @@
|
||||
<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 class="literal">Base</tt> class:
|
||||
to our <code class="literal">Base</code> class:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -359,11 +356,11 @@
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing
|
||||
C++ design. In principle, it should be possible to expose the interface for
|
||||
a 3rd party library without changing it. It is not ideal to add anything
|
||||
to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
|
||||
to our class <code class="computeroutput"><span class="identifier">Base</span></code>. Yet, when
|
||||
you have a virtual function that's going to be overridden in Python and called
|
||||
polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
|
||||
polymorphically <span class="bold"><strong>from C++</strong></span>, we'll need to
|
||||
add some scaffoldings to make things work properly. What we'll do is write
|
||||
a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
|
||||
a class wrapper that derives from <code class="computeroutput"><span class="identifier">Base</span></code>
|
||||
that will unintrusively hook into the virtual functions so that a Python
|
||||
override may be called:
|
||||
</p>
|
||||
@@ -377,21 +374,24 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
|
||||
we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
|
||||
Notice too that in addition to inheriting from <code class="computeroutput"><span class="identifier">Base</span></code>,
|
||||
we also multiply- inherited <code class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></code> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <code class="computeroutput"><span class="identifier">wrapper</span></code> template makes
|
||||
the job of wrapping classes that are meant to overridden in Python, easier.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:<br> <br> <tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to write
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> as:<br> <br>
|
||||
<code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <code class="computeroutput"><span class="identifier">f</span></code>
|
||||
in effect calls the corresponding method of the Python object through <code class="computeroutput"><span class="identifier">get_override</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
|
||||
in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
|
||||
</p>
|
||||
<p>
|
||||
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
|
||||
Finally, exposing <code class="computeroutput"><span class="identifier">Base</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</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">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -399,14 +399,18 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
|
||||
that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
|
||||
<code class="computeroutput"><span class="identifier">pure_virtual</span></code> signals Boost.Python
|
||||
that the function <code class="computeroutput"><span class="identifier">f</span></code> is a
|
||||
pure virtual function.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>member function and methods</b></span><br>
|
||||
<br> Python, like many object oriented languages uses the term <span class="bold"><b>methods</b></span>. Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>member function and
|
||||
methods</strong></span><br> <br> Python, like many object oriented languages
|
||||
uses the term <span class="bold"><strong>methods</strong></span>. Methods correspond
|
||||
roughly to C++'s <span class="bold"><strong>member functions</strong></span>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -414,7 +418,7 @@
|
||||
<p>
|
||||
We've seen in the previous section how classes with pure virtual functions
|
||||
are wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><strong>non</strong></span>-pure-virtual
|
||||
functions instead, the mechanism is a bit different.
|
||||
</p>
|
||||
<p>
|
||||
@@ -429,8 +433,8 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
had a pure virtual function <tt class="literal">f</tt>. If, however, its member
|
||||
function <tt class="literal">f</tt> was not declared as pure virtual:
|
||||
had a pure virtual function <code class="literal">f</code>. If, however, its member
|
||||
function <code class="literal">f</code> was not declared as pure virtual:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -456,15 +460,16 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
|
||||
we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
|
||||
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to rewrite
|
||||
the line with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<br> <br> <tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
Notice how we implemented <code class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></code>. Now,
|
||||
we have to check if there is an override for <code class="computeroutput"><span class="identifier">f</span></code>.
|
||||
If none, then we call <code class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></code>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to rewrite
|
||||
the line with the <code class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></code> as:<br> <br> <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Finally, exposing:
|
||||
</p>
|
||||
@@ -474,10 +479,10 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
|
||||
to its default implementation <tt class="literal">default_f</tt>. There's a special
|
||||
<tt class="literal">def</tt> function for this purpose.
|
||||
Take note that we expose both <code class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></code>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <code class="literal">f</code> and 2) the forwarding function
|
||||
to its default implementation <code class="literal">default_f</code>. There's a special
|
||||
<code class="literal">def</code> function for this purpose.
|
||||
</p>
|
||||
<p>
|
||||
In Python, the results would be as expected:
|
||||
@@ -493,14 +498,14 @@
|
||||
<span class="special">>>></span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
Calling <tt class="literal">base.f()</tt>:
|
||||
Calling <code class="literal">base.f()</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></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>
|
||||
<p>
|
||||
Calling <tt class="literal">derived.f()</tt>:
|
||||
Calling <code class="literal">derived.f()</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||
@@ -510,17 +515,17 @@
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h2>
|
||||
<a name="id453009"></a>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h3>
|
||||
<a name="id3142031"></a>
|
||||
Python Operators
|
||||
</h2>
|
||||
</h3>
|
||||
<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 class="literal">FilePos</tt> and a set of operators
|
||||
Consider a file position class <code class="literal">FilePos</code> and a set of operators
|
||||
that take on FilePos instances:
|
||||
</p>
|
||||
<p>
|
||||
@@ -553,16 +558,16 @@
|
||||
<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 class="literal">self</tt> refers to FilePos object. Also, not every class
|
||||
<tt class="literal">T</tt> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <tt class="literal">other<T>()</tt>
|
||||
in place of an actual <tt class="literal">T</tt> instance when writing "self
|
||||
<code class="literal">self</code> refers to FilePos object. Also, not every class
|
||||
<code class="literal">T</code> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <code class="literal">other<T>()</code>
|
||||
in place of an actual <code class="literal">T</code> instance when writing "self
|
||||
expressions".
|
||||
</p>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||
<a name="id453761"></a>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h3>
|
||||
<a name="id3142715"></a>
|
||||
Special Methods
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
|
||||
supports all of the standard special method names supported by real Python
|
||||
@@ -588,12 +593,11 @@
|
||||
<p>
|
||||
Need we say more?
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt>
|
||||
requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>
|
||||
to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> is used by the method defined by
|
||||
<tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> What is the business of <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>? Well, the method <code class="computeroutput"><span class="identifier">str</span></code> requires the <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>
|
||||
is used by the method defined by <code class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Functions</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="object.html" title=" Object Interface">
|
||||
<link rel="prev" href="exposing.html" title="Exposing Classes">
|
||||
<link rel="next" href="object.html" title="Object Interface">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -46,7 +43,7 @@
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
But before you do, you might want to fire up Python 2.2 or later and type
|
||||
<tt class="literal">>>> import this</tt>.
|
||||
<code class="literal">>>> import this</code>.
|
||||
</p>
|
||||
<pre class="programlisting">>>> import this
|
||||
The Zen of Python, by Tim Peters
|
||||
@@ -65,7 +62,7 @@ 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 <span class="bold"><b>right</b></span> now.
|
||||
Although never is often better than <span class="bold"><strong>right</strong></span> 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!
|
||||
@@ -123,19 +120,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
|
||||
<code class="literal">y</code> is deleted. <code class="literal">x</code> is a dangling reference
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">x.some_method()</tt> is called
|
||||
<code class="literal">x.some_method()</code> is called
|
||||
</li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
</ol></div>
|
||||
<p>
|
||||
We could copy result into a new object:
|
||||
@@ -165,7 +162,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice that the data member <tt class="literal">z</tt> is held by class Y using
|
||||
Notice that the data member <code class="literal">z</code> is held by class Y using
|
||||
a raw pointer. Now we have a potential dangling pointer problem inside Y:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -174,7 +171,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">>>></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>
|
||||
<p>
|
||||
For reference, here's the implementation of <tt class="literal">f</tt> again:
|
||||
For reference, here's the implementation of <code class="literal">f</code> again:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<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">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||
@@ -188,33 +185,33 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
</li>
|
||||
<li>
|
||||
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
|
||||
A pointer to <code class="literal">z</code> is held by <code class="literal">y</code>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
|
||||
<code class="literal">z</code> is deleted. <code class="literal">y.z</code> is a dangling pointer
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">y.z_value()</tt> is called
|
||||
<code class="literal">y.z_value()</code> is called
|
||||
</li>
|
||||
<li>
|
||||
<tt class="literal">z->value()</tt> is called
|
||||
<code class="literal">z->value()</code> is called
|
||||
</li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
</ol></div>
|
||||
<a name="call_policies.call_policies"></a><h2>
|
||||
<a name="id455614"></a>
|
||||
<a name="call_policies.call_policies"></a><h3>
|
||||
<a name="id3144432"></a>
|
||||
Call Policies
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Call Policies may be used in situations such as the example detailed above.
|
||||
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
|
||||
In our example, <code class="literal">return_internal_reference</code> and <code class="literal">with_custodian_and_ward</code>
|
||||
are our friends:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -223,27 +220,27 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span> <span class="special">>());</span>
|
||||
</pre>
|
||||
<p>
|
||||
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
|
||||
What are the <code class="literal">1</code> and <code class="literal">2</code> parameters, you
|
||||
ask?
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&
|
||||
y</tt>, is the owner of the returned reference: <tt class="literal">X&</tt>.
|
||||
The "<tt class="literal">1</tt>" simply specifies the first argument.
|
||||
In short: "return an internal reference <tt class="literal">X&</tt> owned
|
||||
by the 1st argument <tt class="literal">Y& y</tt>".
|
||||
Informs Boost.Python that the first argument, in our case <code class="literal">Y&
|
||||
y</code>, is the owner of the returned reference: <code class="literal">X&</code>.
|
||||
The "<code class="literal">1</code>" simply specifies the first argument.
|
||||
In short: "return an internal reference <code class="literal">X&</code> owned
|
||||
by the 1st argument <code class="literal">Y& y</code>".
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the lifetime of the argument indicated by ward
|
||||
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&
|
||||
y</tt>).
|
||||
(i.e. the 2nd argument: <code class="literal">Z* z</code>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <code class="literal">Y&
|
||||
y</code>).
|
||||
</p>
|
||||
<p>
|
||||
It is also important to note that we have defined two policies above. Two
|
||||
@@ -260,41 +257,43 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
<span class="bold"><b>with_custodian_and_ward</b></span><br> Ties lifetimes
|
||||
<span class="bold"><strong>with_custodian_and_ward</strong></span><br> Ties lifetimes
|
||||
of the arguments
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
|
||||
<span class="bold"><strong>with_custodian_and_ward_postcall</strong></span><br>
|
||||
Ties lifetimes of the arguments and results
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_internal_reference</b></span><br> Ties lifetime
|
||||
<span class="bold"><strong>return_internal_reference</strong></span><br> Ties lifetime
|
||||
of one argument to that of result
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>return_value_policy<T> with T one of:</b></span><br>
|
||||
<span class="bold"><strong>return_value_policy<T> with T one of:</strong></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>reference_existing_object</b></span><br> naive
|
||||
<span class="bold"><strong>reference_existing_object</strong></span><br> naive
|
||||
(dangerous) approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_const_reference</b></span><br> Boost.Python
|
||||
<span class="bold"><strong>copy_const_reference</strong></span><br> Boost.Python
|
||||
v1 approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>copy_non_const_reference</b></span><br>
|
||||
<span class="bold"><strong>copy_non_const_reference</strong></span><br>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><b>manage_new_object</b></span><br> Adopt a pointer
|
||||
<span class="bold"><strong>manage_new_object</strong></span><br> Adopt a pointer
|
||||
and hold the instance
|
||||
</li>
|
||||
</ul></div>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span><br>
|
||||
<br> "Explicit is better than implicit"<br> "In the face
|
||||
of ambiguity, refuse the temptation to guess"<br>
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><strong>Remember the Zen, Luke:</strong></span><br>
|
||||
<br> "Explicit is better than implicit"<br> "In
|
||||
the face of ambiguity, refuse the temptation to guess"<br>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -356,21 +355,21 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
||||
pointers carry no default argument info. Take a function <tt class="literal">f</tt>
|
||||
pointers carry no default argument info. Take a function <code class="literal">f</code>
|
||||
with default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
But the type of a pointer to the function <tt class="literal">f</tt> has no information
|
||||
But the type of a pointer to the function <code class="literal">f</code> has no information
|
||||
about its default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
|
||||
</span></pre>
|
||||
<p>
|
||||
When we pass this function pointer to the <tt class="literal">def</tt> function,
|
||||
When we pass this function pointer to the <code class="literal">def</code> function,
|
||||
there is no way to retrieve the default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -404,10 +403,10 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
are overloaded with a common sequence of initial arguments
|
||||
</li>
|
||||
</ul></div>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
||||
<a name="id457647"></a>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h3>
|
||||
<a name="id3146300"></a>
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Boost.Python now has a way to make it easier. For instance, given a function:
|
||||
</p>
|
||||
@@ -425,19 +424,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</pre>
|
||||
<p>
|
||||
will automatically create the thin wrappers for us. This macro will create
|
||||
a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
|
||||
a class <code class="literal">foo_overloads</code> that can be passed on to <code class="literal">def(...)</code>.
|
||||
The third and fourth macro argument are the minimum arguments and maximum
|
||||
arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
|
||||
arguments, respectively. In our <code class="literal">foo</code> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <code class="literal">def(...)</code>
|
||||
function will automatically add all the foo variants for us:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
|
||||
</pre>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||
<a name="id457963"></a>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h3>
|
||||
<a name="id3146587"></a>
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Objects here, objects there, objects here there everywhere. More frequently
|
||||
than anything else, we need to expose member functions of our classes to
|
||||
@@ -446,7 +445,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
play. Another macro is provided to make this a breeze.
|
||||
</p>
|
||||
<p>
|
||||
Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
Like <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>, <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
may be used to automatically create the thin wrappers for wrapping member
|
||||
functions. Let's have an example:
|
||||
</p>
|
||||
@@ -467,11 +466,11 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
|
||||
will generate a set of thin wrappers for george's <code class="literal">wack_em</code>
|
||||
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
|
||||
the third and fourth macro argument). The thin wrappers are all enclosed
|
||||
in a class named <tt class="literal">george_overloads</tt> that can then be used
|
||||
as an argument to <tt class="literal">def(...)</tt>:
|
||||
in a class named <code class="literal">george_overloads</code> that can then be used
|
||||
as an argument to <code class="literal">def(...)</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
|
||||
@@ -480,13 +479,13 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
|
||||
reference</a> for details.
|
||||
</p>
|
||||
<a name="default_arguments.init_and_optional"></a><h2>
|
||||
<a name="id458323"></a>
|
||||
<a name="default_arguments.init_and_optional"></a><h3>
|
||||
<a name="id3146923"></a>
|
||||
init and optional
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
A similar facility is provided for class constructors, again, with default
|
||||
arguments or a sequence of overloads. Remember <tt class="literal">init<...></tt>?
|
||||
arguments or a sequence of overloads. Remember <code class="literal">init<...></code>?
|
||||
For example, given a class X with a constructor:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -503,7 +502,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</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">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></tt>
|
||||
Notice the use of <code class="literal">init<...></code> and <code class="literal">optional<...></code>
|
||||
to signify the default (optional arguments).
|
||||
</p>
|
||||
</div>
|
||||
@@ -511,8 +510,8 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||
<p>
|
||||
It was mentioned in passing in the previous section that <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
|
||||
and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> can also be
|
||||
It was mentioned in passing in the previous section that <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>
|
||||
and <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> can also be
|
||||
used for overloaded functions and member functions with a common sequence
|
||||
of initial arguments. Here is an example:
|
||||
</p>
|
||||
@@ -554,24 +553,24 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
Notice though that we have a situation now where we have a minimum of zero
|
||||
(0) arguments and a maximum of 3 arguments.
|
||||
</p>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||
<a name="id459095"></a>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h3>
|
||||
<a name="id3147627"></a>
|
||||
Manual Wrapping
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
It is important to emphasize however that <span class="bold"><b>the overloaded
|
||||
functions must have a common sequence of initial arguments</b></span>. Otherwise,
|
||||
It is important to emphasize however that <span class="bold"><strong>the overloaded
|
||||
functions must have a common sequence of initial arguments</strong></span>. Otherwise,
|
||||
our scheme above will not work. If this is not the case, we have to wrap
|
||||
our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
|
||||
</p>
|
||||
<p>
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
|
||||
automatic wrapping through <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
and its sister, <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>. Following
|
||||
up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
|
||||
overloading</a>, since the first 4 overload functins have a common sequence
|
||||
of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
to automatically wrap the first three of the <tt class="literal">def</tt>s and
|
||||
of initial arguments, we can use <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
to automatically wrap the first three of the <code class="literal">def</code>s and
|
||||
manually wrap just the last. Here's how we'll do this:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Building Hello World</title>
|
||||
<title>Building Hello World</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="exposing.html" title="Exposing Classes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -28,26 +25,27 @@
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||
<a name="hello.from_start_to_finish"></a><h2>
|
||||
<a name="id377427"></a>
|
||||
<a name="hello.from_start_to_finish"></a><h3>
|
||||
<a name="id3091224"></a>
|
||||
From Start To Finish
|
||||
</h2>
|
||||
</h3>
|
||||
<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: <span class="bold"><b>bjam</b></span>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Building without bjam</b></span><br>
|
||||
<br> Besides bjam, there are of course other ways to get your module built.
|
||||
What's written here should not be taken as "the one and only way".
|
||||
There are of course other build tools apart from <tt class="literal">bjam</tt>.<br>
|
||||
<br> Take note however that the preferred build tool for Boost.Python is
|
||||
bjam. There are so many ways to set up the build incorrectly. Experience shows
|
||||
that 90% of the "I can't build Boost.Python" problems come from people
|
||||
who had to use a different tool.
|
||||
every boost distribution: <span class="bold"><strong>bjam</strong></span>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Building without bjam</strong></span><br>
|
||||
<br> Besides bjam, there are of course other ways to get your module
|
||||
built. What's written here should not be taken as "the one and only
|
||||
way". There are of course other build tools apart from <code class="literal">bjam</code>.<br>
|
||||
<br> Take note however that the preferred build tool for Boost.Python
|
||||
is bjam. There are so many ways to set up the build incorrectly. Experience
|
||||
shows that 90% of the "I can't build Boost.Python" problems
|
||||
come from people who had to use a different tool. </td></tr></tbody>
|
||||
</table></div>
|
||||
<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
|
||||
@@ -78,7 +76,7 @@
|
||||
if you are on Unix.
|
||||
</p>
|
||||
<p>
|
||||
The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
|
||||
The tutorial example can be found in the directory: <code class="literal">libs/python/example/tutorial</code>.
|
||||
There, you can find:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -90,20 +88,20 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
|
||||
<tt class="literal">Jamfile</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||
The <code class="literal">hello.cpp</code> file is our C++ hello world example. The
|
||||
<code class="literal">Jamfile</code> is a minimalist <span class="emphasis"><em>bjam</em></span> 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 class="literal">bjam</tt> can be executed
|
||||
or somewhere in your path such that <code class="literal">bjam</code> can be executed
|
||||
in the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found <a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.
|
||||
</p>
|
||||
<a name="hello.let_s_jam_"></a><h2>
|
||||
<a name="id377613"></a>
|
||||
<a name="hello.let_s_jam_"></a><h3>
|
||||
<a name="id3091427"></a>
|
||||
Let's Jam!
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
|
||||
</p>
|
||||
@@ -123,13 +121,13 @@ extension hello # Declare a Python extension called hello
|
||||
</pre>
|
||||
<p>
|
||||
First, we need to specify our location. You may place your project anywhere.
|
||||
<tt class="literal">project-root</tt> allows you to do that.
|
||||
<code class="literal">project-root</code> allows you to do that.
|
||||
</p>
|
||||
<pre class="programlisting">project-root ;
|
||||
</pre>
|
||||
<p>
|
||||
By doing so, you'll need a Jamrules file. Simply copy the one in the <a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a>
|
||||
and tweak the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost
|
||||
and tweak the <code class="literal">path-global BOOST_ROOT</code> to where your boost
|
||||
root directory is. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
</p>
|
||||
@@ -139,7 +137,7 @@ extension hello # Declare a Python extension called hello
|
||||
<pre class="programlisting">import python ;
|
||||
</pre>
|
||||
<p>
|
||||
Finally we declare our <tt class="literal">hello</tt> extension:
|
||||
Finally we declare our <code class="literal">hello</code> extension:
|
||||
</p>
|
||||
<pre class="programlisting">extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
@@ -151,10 +149,10 @@ extension hello # Declare a Python extension called hello
|
||||
<p>
|
||||
The last part tells BJam that we are depending on the Boost Python Library.
|
||||
</p>
|
||||
<a name="hello.running_bjam"></a><h2>
|
||||
<a name="id377751"></a>
|
||||
<a name="hello.running_bjam"></a><h3>
|
||||
<a name="id3091556"></a>
|
||||
Running bjam
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
|
||||
interpreter.
|
||||
@@ -164,7 +162,7 @@ extension hello # Declare a Python extension called hello
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
Make sure that the environment is set so that we can invoke the C++ compiler.
|
||||
With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
|
||||
With MSVC, that would mean running the <code class="literal">Vcvars32.bat</code> batch
|
||||
file. For instance:
|
||||
</p>
|
||||
<pre class="programlisting">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||
@@ -177,21 +175,22 @@ extension hello # Declare a Python extension called hello
|
||||
set PYTHON_VERSION=2.2
|
||||
</pre>
|
||||
<p>
|
||||
The above assumes that the Python installation is in <tt class="literal">c:/dev/tools/python</tt>
|
||||
The above assumes that the Python installation is in <code class="literal">c:/dev/tools/python</code>
|
||||
and that we are using Python version 2.2. You'll have to tweak these appropriately.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1", even if that's the version you
|
||||
have.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Be sure not to include a third number, e.g. <span class="bold"><strong>not</strong></span> "2.2.1", even if that's the version
|
||||
you have.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Take note that you may also do that through the Jamrules file we put in our
|
||||
project as detailed above. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
</p>
|
||||
<p>
|
||||
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
|
||||
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamfile"</tt>
|
||||
Now we are ready... Be sure to <code class="literal">cd</code> to <code class="literal">libs/python/example/tutorial</code>
|
||||
where the tutorial <code class="literal">"hello.cpp"</code> and the <code class="literal">"Jamfile"</code>
|
||||
is situated.
|
||||
</p>
|
||||
<p>
|
||||
@@ -254,8 +253,8 @@ b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
if you are on Unix.
|
||||
</p>
|
||||
<p>
|
||||
<tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be
|
||||
found somewhere in your project's <tt class="literal">bin</tt> directory. After a
|
||||
<code class="literal">boost_python.dll</code> and <code class="literal">hello.pyd</code> can be
|
||||
found somewhere in your project's <code class="literal">bin</code> directory. After a
|
||||
successful build, you make it possible for the system to find boost_python.dll
|
||||
or libboost_python.so (usually done with LD_LIBRARY_PATH, DYLD_LIBRARY_PATH,
|
||||
or some other variable on *nix and with PATH on Windows) and for Python to
|
||||
@@ -274,7 +273,7 @@ b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="bold"><b>There you go... Have fun!</b></span>
|
||||
<span class="bold"><strong>There you go... Have fun!</strong></span>
|
||||
</p></blockquote></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Iterators</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="embedding.html" title="Embedding">
|
||||
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||
<link rel="next" href="exception.html" title="Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -33,7 +30,7 @@
|
||||
iterators, but these are two very different beasts.
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><b>C++ iterators:</b></span>
|
||||
<span class="bold"><strong>C++ iterators:</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -48,7 +45,7 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><b>Python Iterators:</b></span>
|
||||
<span class="bold"><strong>Python Iterators:</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -62,8 +59,8 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
|
||||
in x...</b></span></tt> is as follows:
|
||||
The typical Python iteration protocol: <code class="literal"><span class="bold"><strong>for y
|
||||
in x...</strong></span></code> is as follows:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -77,7 +74,7 @@
|
||||
</span></pre>
|
||||
<p>
|
||||
Boost.Python provides some mechanisms to make C++ iterators play along nicely
|
||||
as Python iterators. What we need to do is to produce appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that
|
||||
as Python iterators. What we need to do is to produce appropriate <code class="computeroutput"><span class="identifier">__iter__</span></code> function from C++ iterators that
|
||||
is compatible with the Python iteration protocol. For example:
|
||||
</p>
|
||||
<p>
|
||||
@@ -94,7 +91,7 @@
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>range</b></span>
|
||||
<span class="bold"><strong>range</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
We can create a Python savvy iterator using the range function:
|
||||
@@ -122,14 +119,14 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><b>iterator</b></span>
|
||||
<span class="bold"><strong>iterator</strong></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc"><li>
|
||||
iterator<T, Policies>()
|
||||
</li></ul></div>
|
||||
<p>
|
||||
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
|
||||
calls <tt class="literal">range</tt> with &T::begin, &T::end.
|
||||
Given a container <code class="literal">T</code>, iterator is a shortcut that simply
|
||||
calls <code class="literal">range</code> with &T::begin, &T::end.
|
||||
</p>
|
||||
<p>
|
||||
Let's put this into action... Here's an example from some hypothetical bogon
|
||||
@@ -155,14 +152,14 @@
|
||||
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>stl_input_iterator</b></span>
|
||||
<span class="bold"><strong>stl_input_iterator</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
|
||||
we wish to go the other way, though: we'd like to pass a Python sequence to
|
||||
an STL algorithm or use it to initialize an STL container. We need to make
|
||||
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></tt>.
|
||||
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
|
||||
a Python iterator look like an STL iterator. For that, we use <code class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></code>.
|
||||
Consider how we might implement a function that exposes <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></code> to Python:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -181,7 +178,7 @@
|
||||
</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
|
||||
Now in Python, we can assign any integer sequence to <code class="computeroutput"><span class="identifier">list_int</span></code>
|
||||
objects:
|
||||
</p>
|
||||
<p>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> Object Interface</title>
|
||||
<title>Object Interface</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="functions.html" title="Functions">
|
||||
@@ -38,13 +35,13 @@
|
||||
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 class="literal">object</tt>. We shall see in this
|
||||
are just instances of class <code class="literal">object</code>. 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 class="literal">object</tt>s are as close as possible to Python. This should
|
||||
C++ <code class="literal">object</code>s are as close as possible to Python. This should
|
||||
minimize the learning curve significantly.
|
||||
</p>
|
||||
<p>
|
||||
@@ -54,10 +51,10 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||
<p>
|
||||
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the
|
||||
intricacies of dealing with <tt class="literal">PyObject</tt>s such as managing
|
||||
reference counting are handled by the <tt class="literal">object</tt> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
|
||||
Class <code class="literal">object</code> wraps <code class="literal">PyObject*</code>. All the
|
||||
intricacies of dealing with <code class="literal">PyObject</code>s such as managing
|
||||
reference counting are handled by the <code class="literal">object</code> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <code class="literal">object</code>s
|
||||
can in fact be explicitly constructed from any C++ object.
|
||||
</p>
|
||||
<p>
|
||||
@@ -102,7 +99,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python comes with a set of derived <tt class="literal">object</tt> types
|
||||
Boost.Python comes with a set of derived <code class="literal">object</code> types
|
||||
corresponding to that of Python's:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -126,32 +123,32 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
These derived <tt class="literal">object</tt> types act like real Python types.
|
||||
These derived <code class="literal">object</code> types act like real Python types.
|
||||
For instance:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==></span> <span class="string">"1"</span>
|
||||
</pre>
|
||||
<p>
|
||||
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
|
||||
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
|
||||
has a <tt class="literal">keys()</tt> method:
|
||||
Wherever appropriate, a particular derived <code class="literal">object</code> has
|
||||
corresponding Python type's methods. For instance, <code class="literal">dict</code>
|
||||
has a <code class="literal">keys()</code> method:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
<tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
<code class="literal">make_tuple</code> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
Example:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
|
||||
In C++, when Boost.Python <code class="literal">object</code>s are used as arguments
|
||||
to functions, subtype matching is required. For example, when a function
|
||||
<tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <tt class="literal">str</tt> type and subtypes.
|
||||
<code class="literal">f</code>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <code class="literal">str</code> type and subtypes.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||
@@ -175,15 +172,16 @@
|
||||
<span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
|
||||
% x,y,z</tt> in Python, which is useful since there's no easy way to
|
||||
Demonstrates that you can write the C++ equivalent of <code class="literal">"format"
|
||||
% x,y,z</code> in Python, which is useful since there's no easy way to
|
||||
do that in std C++.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>Beware</b></span> the common
|
||||
pitfall of forgetting that the constructors of most of Python's mutable types
|
||||
make copies, just as in Python.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>Beware</strong></span> the
|
||||
common pitfall of forgetting that the constructors of most of Python's
|
||||
mutable types make copies, just as in Python. </td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Python:
|
||||
</p>
|
||||
@@ -198,12 +196,12 @@
|
||||
<span class="identifier">dict</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> <span class="comment">// copies x.__dict__
|
||||
</span><span class="identifier">d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies the copy
|
||||
</span></pre>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||
<a name="id461067"></a>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h3>
|
||||
<a name="id3149441"></a>
|
||||
class_<T> as objects
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt>
|
||||
Due to the dynamic nature of Boost.Python objects, any <code class="literal">class_<T></code>
|
||||
may also be one of these types! The following code snippet wraps the class
|
||||
(type) object.
|
||||
</p>
|
||||
@@ -225,15 +223,15 @@
|
||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||
<p>
|
||||
At some point, we will need to get C++ values out of object instances. This
|
||||
can be achieved with the <tt class="literal">extract<T></tt> function. Consider
|
||||
can be achieved with the <code class="literal">extract<T></code> function. Consider
|
||||
the following:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
|
||||
</span></pre>
|
||||
<p>
|
||||
In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
|
||||
can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
|
||||
In the code above, we got a compiler error because Boost.Python <code class="literal">object</code>
|
||||
can't be implicitly converted to <code class="literal">double</code>s. Instead, what
|
||||
we wanted to do above can be achieved by writing:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -243,14 +241,14 @@
|
||||
</pre>
|
||||
<p>
|
||||
The first line attempts to extract the "length" attribute of the
|
||||
Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
|
||||
Boost.Python <code class="literal">object</code>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <code class="literal">Vec2</code> object from held by the Boost.Python <code class="literal">object</code>.
|
||||
</p>
|
||||
<p>
|
||||
Take note that we said "attempt to" above. What if the Boost.Python
|
||||
<tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
|
||||
<code class="literal">object</code> does not really hold a <code class="literal">Vec2</code>
|
||||
type? This is certainly a possibility considering the dynamic nature of Python
|
||||
<tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
|
||||
<code class="literal">object</code>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>
|
||||
@@ -260,7 +258,7 @@
|
||||
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract<T></tt>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <code class="literal">extract<T></code>
|
||||
facility in fact solves the mutable copying problem:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -273,8 +271,8 @@
|
||||
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
|
||||
has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums
|
||||
to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes
|
||||
has no <code class="literal">enum</code> type, we'll often want to expose our C++ enums
|
||||
to Python as an <code class="literal">int</code>. Boost.Python's enum facility makes
|
||||
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:
|
||||
@@ -293,16 +291,18 @@
|
||||
</pre>
|
||||
<p>
|
||||
can be used to expose to Python. The new enum type is created in the current
|
||||
<tt class="literal">scope()</tt>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <tt class="literal">int</tt>
|
||||
<code class="literal">scope()</code>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <code class="literal">int</code>
|
||||
type which is associated with the C++ type passed as its first parameter.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>what is a scope?</b></span><br>
|
||||
<br> The scope is a class that has an associated global Python object which
|
||||
controls the Python namespace in which new extension classes and wrapped
|
||||
functions will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>what is a scope?</strong></span><br>
|
||||
<br> The scope is a class that has an associated global Python object
|
||||
which controls the Python namespace in which new extension classes
|
||||
and wrapped functions will be defined as attributes. Details can be
|
||||
found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
You can access those values in Python as
|
||||
</p>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title> General Techniques</title>
|
||||
<title>General Techniques</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exception.html" title=" Exception Translation">
|
||||
<link rel="prev" href="exception.html" title="Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
@@ -53,7 +50,7 @@
|
||||
<p>
|
||||
We have a C++ library that works with sounds: reading and writing various
|
||||
formats, applying filters to the sound data, etc. It is named (conveniently)
|
||||
<tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
|
||||
<code class="literal">sounds</code>. Our library already has a neat C++ namespace hierarchy,
|
||||
like so:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -96,15 +93,16 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
|
||||
<tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The extension <tt class="literal">.pyd</tt> is used for python
|
||||
extension modules, which are just shared libraries. Using the default for
|
||||
your system, like <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt>
|
||||
for Windows, works just as well.
|
||||
Compiling these files will generate the following Python extensions: <code class="literal">core.pyd</code>,
|
||||
<code class="literal">io.pyd</code> and <code class="literal">filters.pyd</code>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The extension <code class="literal">.pyd</code> is used
|
||||
for python extension modules, which are just shared libraries. Using
|
||||
the default for your system, like <code class="literal">.so</code> for Unix and
|
||||
<code class="literal">.dll</code> for Windows, works just as well.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:
|
||||
</p>
|
||||
@@ -115,12 +113,12 @@
|
||||
io.pyd
|
||||
</pre>
|
||||
<p>
|
||||
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
|
||||
<tt class="literal">sounds/</tt> is actually a Python package. It can be a empty
|
||||
The file <code class="literal">__init__.py</code> is what tells Python that the directory
|
||||
<code class="literal">sounds/</code> is actually a Python package. It can be a empty
|
||||
file, but can also perform some magic, that will be shown later.
|
||||
</p>
|
||||
<p>
|
||||
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
|
||||
Now our package is ready. All the user has to do is put <code class="literal">sounds</code>
|
||||
into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||
and fire up the interpreter:
|
||||
</p>
|
||||
@@ -159,7 +157,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
Note that we added an underscore to the module name. The filename will have
|
||||
to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
|
||||
to be changed to <code class="literal">_core.pyd</code> as well, and we do the same
|
||||
to the other extension modules. Now, we change our package hierarchy like
|
||||
so:
|
||||
</p>
|
||||
@@ -187,11 +185,11 @@
|
||||
<span class="special">>>></span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span>
|
||||
</pre>
|
||||
<p>
|
||||
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
|
||||
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
|
||||
which is not what we want. But here enters the <code class="literal">__init__.py</code>
|
||||
magic: everything that is brought to the <code class="literal">__init__.py</code> namespace
|
||||
can be accessed directly by the user. So, all we have to do is bring the
|
||||
entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
|
||||
So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
|
||||
entire namespace from <code class="literal">_core.pyd</code> to <code class="literal">core/__init__.py</code>.
|
||||
So add this line of code to <code class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
|
||||
@@ -208,10 +206,10 @@
|
||||
with the additional benefit that we can easily add pure Python functions
|
||||
to any module, in a way that the user can't tell the difference between a
|
||||
C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span>
|
||||
Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
|
||||
package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
|
||||
filters in sequence in the given <tt class="literal">sound</tt> object. We create
|
||||
a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
|
||||
Python function, <code class="literal">echo_noise</code>, to the <code class="literal">filters</code>
|
||||
package. This function applies both the <code class="literal">echo</code> and <code class="literal">noise</code>
|
||||
filters in sequence in the given <code class="literal">sound</code> object. We create
|
||||
a file named <code class="literal">sounds/filters/echo_noise.py</code> and code our
|
||||
function:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -222,14 +220,14 @@
|
||||
<span class="keyword">return</span> <span class="identifier">s</span>
|
||||
</pre>
|
||||
<p>
|
||||
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
|
||||
Next, we add this line to <code class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</code>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
|
||||
</pre>
|
||||
<p>
|
||||
And that's it. The user now accesses this function like any other function
|
||||
from the <tt class="literal">filters</tt> package:
|
||||
from the <code class="literal">filters</code> package:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||
@@ -263,7 +261,7 @@
|
||||
</p>
|
||||
<p>
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class <tt class="literal">point</tt> in C++:
|
||||
we have a class <code class="literal">point</code> in C++:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -277,7 +275,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
|
||||
Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
|
||||
Packages</a>, we can code directly into <code class="literal">geom/__init__.py</code>:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -292,7 +290,7 @@
|
||||
</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">__str__</span> <span class="special">=</span> <span class="identifier">point_str</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><b>All</b></span> point instances created from C++ will
|
||||
<span class="bold"><strong>All</strong></span> point instances created from C++ will
|
||||
also have this member function! This technique has several advantages:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -391,7 +389,7 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
|
||||
Now you create a file <code class="literal">main.cpp</code>, which contains the <code class="literal">BOOST_PYTHON_MODULE</code>
|
||||
macro, and call the various export functions inside it.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -427,17 +425,19 @@
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <tt class="literal">--multiple</tt> option, that generates the
|
||||
wrappers in various files as demonstrated here.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This method is useful too if you are getting the error
|
||||
message <span class="emphasis"><em>"fatal error C1204:Compiler limit:internal structure
|
||||
overflow"</em></span> when compiling a large source file, as explained
|
||||
in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <code class="literal">--multiple</code> option, that generates
|
||||
the wrappers in various files as demonstrated here.</td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This method is useful too if you are getting the
|
||||
error message <span class="emphasis"><em>"fatal error C1204:Compiler limit:internal
|
||||
structure overflow"</em></span> when compiling a large source file,
|
||||
as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
|
||||
@@ -1365,11 +1365,6 @@ create a new scope around a class:
|
||||
|
||||
[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]]
|
||||
@@ -1396,17 +1391,17 @@ 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.
|
||||
To be able to embed python into your programs, you have to link to
|
||||
both Boost.Python's as well as Python's own runtime library.
|
||||
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
Boost.Python's 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
|
||||
Python's 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.
|
||||
|
||||
@@ -1444,7 +1439,11 @@ steps:
|
||||
|
||||
# Call other Python C API routines to use the interpreter.\n\n
|
||||
|
||||
# Call Py_Finalize() to stop the interpreter and release its resources.
|
||||
[/ # Call Py_Finalize() to stop the interpreter and release its resources.]
|
||||
|
||||
[blurb __note__ [*Note that at this time you must not call Py_Finalize() to stop the
|
||||
interpreter. This may be fixed in a future version of boost.python.]
|
||||
]
|
||||
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
|
||||
@@ -1461,171 +1460,76 @@ messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
|
||||
[@../../../v2/object.html object] class templates to automate the process.
|
||||
|
||||
[h2 Reference-counting handles and objects]
|
||||
|
||||
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:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
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 __note__ [*Handle is a class ['template], so why haven't we been using any template parameters?]\n
|
||||
\n
|
||||
[^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:
|
||||
Boost.python provides three related functions to run Python code from C++.
|
||||
|
||||
PyObject* PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
|
||||
object eval(str expression, object globals = object(), object locals = object())
|
||||
object exec(str code, object globals = object(), object locals = object())
|
||||
object exec_file(str filename, object globals = object(), object locals = object())
|
||||
|
||||
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.
|
||||
eval evaluates the given expression and returns the resulting value.
|
||||
exec executes the given code (typically a set of statements) returning the result,
|
||||
and exec_file executes the code contained in the given file.
|
||||
|
||||
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
|
||||
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:
|
||||
Boost.python provides a function to import a module:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
object import(str name)
|
||||
|
||||
import imports a python module (potentially loading it into the running process
|
||||
first), and returns it.
|
||||
|
||||
Let's import the [^__main__] module and run some Python code in its namespace:
|
||||
|
||||
object main_module = import("__main__");
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
"hello.close()"
|
||||
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
));
|
||||
|
||||
Because the Python/C API doesn't know anything about [^object]s, we used
|
||||
the object's [^ptr] member function to retrieve the [^PyObject*].
|
||||
object ignored = exec("hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
"hello.close()",
|
||||
main_namespace);
|
||||
|
||||
This should create a file called 'hello.txt' in the current directory
|
||||
containing a phrase that is well-known in programming circles.
|
||||
|
||||
[blurb
|
||||
__note__ [*Note] that we wrap the return value of PyRun_String in a
|
||||
(nameless) [^handle] even though we are not interested in it. If we didn't
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
|
||||
]
|
||||
[h2 Manipulating Python objects]
|
||||
|
||||
[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
|
||||
above, and in the [@python/object.html previous section]: the aptly
|
||||
named [^object] class and it's derivatives. We've already seen that they
|
||||
can be constructed from a [^handle]. The following examples should further
|
||||
illustrate this fact:
|
||||
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
Often we'd like to have a class to manipulate Python objects.
|
||||
But we have already seen such a class above, and in the
|
||||
[@python/object.html previous section]: the aptly named [^object] class
|
||||
and its derivatives. We've already seen that they can be constructed from
|
||||
a [^handle]. The following examples should further illustrate this fact:
|
||||
|
||||
object main_module = import("__main__");
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"result = 5 ** 2"
|
||||
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
));
|
||||
|
||||
object ignored = exec("result = 5 ** 2", main_namespace);
|
||||
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()))
|
||||
));
|
||||
the dictionary. Another way to achieve the same result is to use eval instead,
|
||||
which returns the result directly:
|
||||
|
||||
object result = eval("5 ** 2");
|
||||
int five_squared = extract<int>(result);
|
||||
|
||||
[blurb
|
||||
__note__ [*Note] that [^object]'s member function to return the wrapped
|
||||
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
|
||||
take into account the different functions that [^object] and [^handle]
|
||||
perform.
|
||||
]
|
||||
|
||||
[h2 Exception handling]
|
||||
|
||||
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]:
|
||||
If an exception occurs in the evaluation of the python expression,
|
||||
[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown:
|
||||
|
||||
try
|
||||
{
|
||||
object result((handle<>(PyRun_String(
|
||||
"5/0"
|
||||
, Py_eval_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr()))
|
||||
));
|
||||
|
||||
object result = eval("5/0");
|
||||
// execution will never get here:
|
||||
int five_divided_by_zero = extract<int>(result);
|
||||
}
|
||||
catch(error_already_set)
|
||||
catch(error_already_set const &)
|
||||
{
|
||||
// handle the exception in some way
|
||||
}
|
||||
@@ -1639,7 +1543,7 @@ 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)
|
||||
catch(error_already_set const &)
|
||||
{
|
||||
if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
|
||||
{
|
||||
@@ -1655,21 +1559,6 @@ standard exceptions]:
|
||||
(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
|
||||
|
||||
[endsect]
|
||||
[endsect] [/ Embedding]
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#eval-spec"><code>eval</code></a></dt>
|
||||
<dt><a href="#exec-spec"><code>exec</code></a></dt>
|
||||
<dt><a href="#exec_file-spec"><code>exec_file</code></a></dt>
|
||||
</dl>
|
||||
@@ -52,6 +53,23 @@
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
|
||||
<h3><a name="eval-spec"></a><code>eval</code></h3>
|
||||
<pre>
|
||||
object eval(str expression,
|
||||
object globals = object(),
|
||||
object locals = object());
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
Evaluate Python expression from <code>expression</code> in the context
|
||||
specified by the dictionaries <code>globals</code> and <code>locals</code>.
|
||||
</dt>
|
||||
<dt><b>Returns:</b>
|
||||
An instance of <a href="object.html#object-spec">object</a>
|
||||
which holds the value of the expression.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="exec-spec"></a><code>exec</code></h3>
|
||||
<pre>
|
||||
object exec(str code,
|
||||
|
||||
@@ -977,6 +977,7 @@
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="exec.html#eval-spec">eval</a></dt>
|
||||
<dt><a href="exec.html#exec-spec">exec</a></dt>
|
||||
<dt><a href="exec.html#exec_file-spec">exec_file</a></dt>
|
||||
</dl>
|
||||
|
||||
Reference in New Issue
Block a user