mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 17:52:17 +00:00
Compare commits
91 Commits
boost-1.34
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9e29281b4 | ||
|
|
04e54d670c | ||
|
|
dd7c0a7f3d | ||
|
|
9de994c0d1 | ||
|
|
e9caacc428 | ||
|
|
5070e84f70 | ||
|
|
fe23d9885f | ||
|
|
e7ee17b71b | ||
|
|
5edb63d01c | ||
|
|
f4b3aab7d4 | ||
|
|
6af67d1a4c | ||
|
|
16d975ba5c | ||
|
|
4fc5cafd40 | ||
|
|
1b5cd10f7c | ||
|
|
0f91872518 | ||
|
|
dc6b2979e4 | ||
|
|
50034140c4 | ||
|
|
08a6f35ec2 | ||
|
|
67236ffbad | ||
|
|
96ab7a80a4 | ||
|
|
d8c3ff199e | ||
|
|
0c4ebef579 | ||
|
|
8fe9d41b58 | ||
|
|
8a4590b2ef | ||
|
|
d67b040683 | ||
|
|
2db61657f2 | ||
|
|
6d2ee96ba3 | ||
|
|
a74c8e3da3 | ||
|
|
9f4d39d9fe | ||
|
|
31c19644ed | ||
|
|
600d444136 | ||
|
|
c3bd0fcbad | ||
|
|
991a7c198a | ||
|
|
9b67f0447d | ||
|
|
b714f6cc23 | ||
|
|
479a6ba4fc | ||
|
|
d78836b828 | ||
|
|
7a59131d37 | ||
|
|
5ab00bc9c8 | ||
|
|
94500ae36d | ||
|
|
5e5d34cc36 | ||
|
|
c6f2aa4ef2 | ||
|
|
c7fb2f7047 | ||
|
|
afedc1cd9a | ||
|
|
070e02d7d5 | ||
|
|
ccc56c2a4c | ||
|
|
e00a88ff49 | ||
|
|
e527bc860f | ||
|
|
921e306b9a | ||
|
|
bed1d26904 | ||
|
|
41a342f026 | ||
|
|
cee8e07046 | ||
|
|
0806e89964 | ||
|
|
f5421ca6b2 | ||
|
|
eea7697175 | ||
|
|
777ce7b561 | ||
|
|
864ece5539 | ||
|
|
2610eb9acb | ||
|
|
567a2c7b89 | ||
|
|
05070faf12 | ||
|
|
ad8069314d | ||
|
|
9366c48351 | ||
|
|
5a14319753 | ||
|
|
279a4f7888 | ||
|
|
d3418d494c | ||
|
|
c839427246 | ||
|
|
dd3a136b18 | ||
|
|
48696918de | ||
|
|
88be35ddc2 | ||
|
|
9ee0d36a1d | ||
|
|
f240e0bab6 | ||
|
|
4081605e4b | ||
|
|
f332ff2d89 | ||
|
|
ec77608840 | ||
|
|
f5a69a1dab | ||
|
|
a1e865061c | ||
|
|
596e92404a | ||
|
|
2640f5af94 | ||
|
|
0605e9fdcf | ||
|
|
cf68da0b19 | ||
|
|
d3c474b295 | ||
|
|
c9300e07c2 | ||
|
|
cab94a7bba | ||
|
|
caa9cb8268 | ||
|
|
66ac61450e | ||
|
|
59f81def56 | ||
|
|
92862028b7 | ||
|
|
b0ba7dfc50 | ||
|
|
fe3abeda9f | ||
|
|
3fdfb30e33 | ||
|
|
cdcf8633bb |
@@ -7,26 +7,12 @@ import modules ;
|
||||
|
||||
import python ;
|
||||
|
||||
if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
|
||||
{
|
||||
# Attempt default configuration of python
|
||||
import toolset : using ;
|
||||
using python ;
|
||||
|
||||
if ! [ python.configured ]
|
||||
{
|
||||
ECHO "WARNING: No python installation configured and autoconfiguration" ;
|
||||
ECHO " failed. See http://www.boost.org/libs/python/doc/building.html" ;
|
||||
ECHO " for configuration instructions or pass --without-python to" ;
|
||||
ECHO " suppress this message and silently skip all Boost.Python targets" ;
|
||||
}
|
||||
}
|
||||
|
||||
if [ python.configured ] {
|
||||
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
;
|
||||
: source-location ../src
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
@@ -77,13 +63,11 @@ lib boost_python
|
||||
# import library, as usage requirements.
|
||||
<library>/python//python_for_extensions
|
||||
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
|
||||
: # default build
|
||||
<link>shared
|
||||
: # usage requirements
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<link>shared:<define>BOOST_PYTHON_DYNAMIC_LIB
|
||||
;
|
||||
}
|
||||
else
|
||||
|
||||
23
doc/Jamfile
Normal file
23
doc/Jamfile
Normal file
@@ -0,0 +1,23 @@
|
||||
# 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)
|
||||
import docutils ;
|
||||
|
||||
import path ;
|
||||
sources = building.rst ;
|
||||
bases = $(sources:S=) ;
|
||||
|
||||
# This is a path relative to the html/ subdirectory where the
|
||||
# generated output will eventually be moved.
|
||||
stylesheet = "--stylesheet=../../../rst.css" ;
|
||||
|
||||
for local b in $(bases)
|
||||
{
|
||||
html $(b) : $(b).rst :
|
||||
|
||||
<docutils-html>"-gdt --source-url="./$(b).rst" --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript "$(stylesheet)
|
||||
;
|
||||
}
|
||||
|
||||
alias htmls : $(bases) ;
|
||||
stage . : $(bases) ;
|
||||
@@ -1,461 +1,415 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
|
||||
<title>Boost C++ Libraries: Boost.Python Build and Test HOWTO</title>
|
||||
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="logo-boost-python-build-and-test-howto">
|
||||
<h1 class="title"><a class="reference" href="../index.htm"><img alt="Boost C++ Libraries:" class="boost-logo" src="../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
|
||||
|
||||
<!-- 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 name="generator" content=
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
<title>Boost.Python - Building and Testing</title>
|
||||
</head>
|
||||
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Building and Testing</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="Reference">
|
||||
<dt><a href="#requirements">Requirements</a></dt>
|
||||
|
||||
<dt><a href="#building">Building Boost.Python</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="#configuration">Configuration</a></dt>
|
||||
|
||||
<dt><a href="#cygwin_configuration">Configuration for Cygwin GCC
|
||||
from a Windows prompt</a></dt>
|
||||
|
||||
<dt><a href="#results">Results</a></dt>
|
||||
|
||||
<dt><a href="#cygwin">Notes for Cygwin GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#mingw">Notes for MinGW (and Cygwin with -mno-cygwin)
|
||||
GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#testing">Testing</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#building_ext">Building your Extension Module</a></dt>
|
||||
|
||||
<dt><a href="#variants">Build Variants</a></dt>
|
||||
|
||||
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
||||
IDE</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="requirements">Requirements</a></h2>
|
||||
<b>Boost.Python</b> requires <a href=
|
||||
"http://www.python.org/2.2">Python 2.2</a> <i>or <a href=
|
||||
"http://www.python.org">newer</a></i>.
|
||||
|
||||
<h2><a name="building">Building Boost.Python</a></h2>
|
||||
|
||||
<p>Normally, Boost.Python extension modules must be linked with the
|
||||
<code>boost_python</code> shared library. In special circumstances you
|
||||
may want to link to a static version of the <code>boost_python</code>
|
||||
library, but if multiple Boost.Python extension modules are used
|
||||
together, it will prevent sharing of types across extension modules, and
|
||||
consume extra code space. To build <code>boost_python</code>, use <a
|
||||
href="../../../tools/build/v1/build_system.htm">Boost.Build</a> in the
|
||||
usual way from the <code>libs/python/build</code> subdirectory of your
|
||||
boost installation (if you have already built boost from the top level
|
||||
this may have no effect, since the work is already done).</p>
|
||||
|
||||
<h3><a name="configuration">Basic Configuration</a></h3> You may
|
||||
need to configure the following variables to point Boost.Build at
|
||||
your Python installation. Variables can be either set in the
|
||||
environment or passed on the <code>bjam</code> command-line
|
||||
as <code>-s</code><i>name</i><code>=</code><i>value</i>. Variable
|
||||
names are case-sensitive.
|
||||
|
||||
<table border="1" summary="build configuration variables">
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<tr>
|
||||
<td><code>PYTHON_VERSION</code></td>
|
||||
|
||||
<td>The The 2-part python Major.Minor version number</td>
|
||||
|
||||
<td><code>2.4</code></td>
|
||||
|
||||
<td>Be sure not to include a third number, e.g. <b>not</b>
|
||||
"<code>2.2.1</code>", even if that's the version you have.</td>
|
||||
</tr>
|
||||
|
||||
<td><code>PYTHON_ROOT</code></td>
|
||||
|
||||
<td>The root directory of your Python installation</td>
|
||||
|
||||
<td>Windows: <code>c:/Python</code><i>(10*Version)</i>, e.g. <code>c:/Python24</code>
|
||||
<br>
|
||||
*nix/Cygwin: <code>/usr</code></td>
|
||||
|
||||
<td>On *nix, this should be the <code>--prefix=</code> directory used
|
||||
to configure Python when it was built and installed.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_INCLUDES</code></td>
|
||||
|
||||
<td>path to Python <code>#include</code> directories</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>PYTHON_LIB_PATH</code></td>
|
||||
|
||||
<td>path to Python library object.</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="cygwin_configuration">Configuration for Cygwin GCC from a
|
||||
Windows prompt</a></h3>
|
||||
The following settings may be useful when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC (not MinGW) from a Windows command
|
||||
shell using a Windows build of <code>bjam</code>. <b>If
|
||||
"<code>bjam -v</code>" does not report "<code>OS=NT</code>", these
|
||||
settings do not apply to you</b>; you should use the <a href=
|
||||
"#configuration">normal configuration</a> variables instead. They are
|
||||
only useful when building and testing with multiple toolsets on Windows
|
||||
using a single build command, since Cygwin GCC requires a different build
|
||||
of Python.
|
||||
|
||||
<table border="1" summary=
|
||||
"Cygwin GCC under NT build configuration variables">
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]VERSION</code></td>
|
||||
|
||||
<td>The version of python being used under Cygwin.</td>
|
||||
|
||||
<td>$(PYTHON_VERSION)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
|
||||
|
||||
<td>*nix-style path containing the <code>include/</code> directory
|
||||
containing
|
||||
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
|
||||
|
||||
<td>$(PYTHON_ROOT)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]LIB_PATH</code></td>
|
||||
|
||||
<td>path containing the user's Cygwin Python import lib
|
||||
<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll.a</code></td>
|
||||
|
||||
<td>Autoconfigured from <code>CYGWIN_PYTHON_ROOT</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]DLL_PATH</code></td>
|
||||
|
||||
<td>path containing the user's Cygwin Python dll
|
||||
(<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll</code>)</td>
|
||||
|
||||
<td><code>/bin</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="cygwin">Notes for Cygwin GCC Users</a></h3>
|
||||
|
||||
<p>If you are using Cygwin GCC to build extension modules, you must use a
|
||||
Cygwin build of Python. The regular Win32 Python installation that you
|
||||
can download from <a href="http://www.python.org">python.org</a> will not
|
||||
work with your compiler because the dynamic linking conventions are
|
||||
different (you can use <a href="http://www.mingw.org/">MinGW</a> GCC if
|
||||
you want to build extension modules which are compatible with a stock
|
||||
Win32 Python). The Cygwin installer may be able to install an appropriate
|
||||
version of Python, or you can follow the traditional <a href=
|
||||
"http://www.python.org/download/download_source.html">Unix installation
|
||||
process</a> to build Python from source.</p>
|
||||
|
||||
<p>The special build configuration variables listed <a href=
|
||||
"#cygwin_configuration">above</a> make it possible to use a regular Win32
|
||||
build of bjam to build and test Boost.Python and Boost.Python extensions
|
||||
using Cygwin GCC and targeting a Cygwin build of Python.</p>
|
||||
|
||||
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
|
||||
Users</a></h3>
|
||||
|
||||
<p>If you are using a version of Python prior to 2.4.1 with a
|
||||
MinGW prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will
|
||||
need to create a MinGW-compatible version of the Python library;
|
||||
the one shipped with Python will only work with a
|
||||
Microsoft-compatible linker. Follow the instructions in the
|
||||
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
|
||||
chapter in <a href=
|
||||
"http://www.python.org/doc/current/inst/index.html">Installing Python
|
||||
Modules</a> to create <code>libpythonXX.a</code>, where <code>XX</code>
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.</p>
|
||||
|
||||
<h3><a name="results">Results</a></h3>
|
||||
|
||||
<p>The build process will create a
|
||||
<code>libs/python/build/bin-stage</code> subdirectory of the boost root
|
||||
(or of <code>$(ALL_LOCATE_TARGET)</code>, if you have set that variable),
|
||||
containing the built libraries. The libraries are actually built to
|
||||
unique directories for each toolset and variant elsewhere in the
|
||||
filesystem, and copied to the <code>bin-stage</code> directory as a
|
||||
convenience, so if you build with multiple toolsets at once, the product
|
||||
of later toolsets will overwrite that of earlier toolsets in
|
||||
<code>bin-stage</code>.</p>
|
||||
|
||||
<h3><a name="testing">Testing</a></h3>
|
||||
|
||||
<p>To build and test Boost.Python, start from the
|
||||
<code>libs/python/test</code> directory and invoke</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> test
|
||||
<!-- file LICENSE_1_0.txt or copy at -->
|
||||
<!-- http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<div class="contents sidebar small topic">
|
||||
<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
|
||||
<ul class="auto-toc simple">
|
||||
<li><a class="reference" href="#requirements" id="id20" name="id20">1 Requirements</a></li>
|
||||
<li><a class="reference" href="#background" id="id21" name="id21">2 Background</a></li>
|
||||
<li><a class="reference" href="#getting-boost-python-binaries" id="id22" name="id22">3 Getting Boost.Python Binaries</a><ul class="auto-toc">
|
||||
<li><a class="reference" href="#no-install-quickstart" id="id23" name="id23">3.1 No-Install Quickstart</a></li>
|
||||
<li><a class="reference" href="#installing-boost-python-on-your-system" id="id24" name="id24">3.2 Installing Boost.Python on your System</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#configuring-boost-build" id="id25" name="id25">4 Configuring Boost.Build</a></li>
|
||||
<li><a class="reference" href="#building-an-extension-module" id="id26" name="id26">5 Building an Extension Module</a></li>
|
||||
<li><a class="reference" href="#testing" id="id27" name="id27">6 Testing</a></li>
|
||||
<li><a class="reference" href="#advanced-configuration" id="id28" name="id28">7 Advanced Configuration</a><ul class="auto-toc">
|
||||
<li><a class="reference" href="#python-configuration-parameters" id="id29" name="id29">7.1 Python Configuration Parameters</a></li>
|
||||
<li><a class="reference" href="#examples" id="id30" name="id30">7.2 Examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#choosing-a-boost-python-library-binary" id="id31" name="id31">8 Choosing a Boost.Python Library Binary</a><ul class="auto-toc">
|
||||
<li><a class="reference" href="#the-dynamic-binary" id="id32" name="id32">8.1 The Dynamic Binary</a></li>
|
||||
<li><a class="reference" href="#the-static-binary" id="id33" name="id33">8.2 The Static Binary</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#notes-for-mingw-and-cygwin-with-mno-cygwin-gcc-users" id="id34" name="id34">9 Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id20" id="requirements" name="requirements">1 Requirements</a></h1>
|
||||
<p>Boost.Python requires <a class="reference" href="http://www.python.org/2.2">Python 2.2</a><a class="footnote-reference" href="#id16" id="id2" name="id2"><sup>1</sup></a> <em>or</em> <a class="reference" href="http://www.python.org"><em>newer</em></a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id21" id="background" name="background">2 Background</a></h1>
|
||||
<p>There are two basic models for combining C++ and Python:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="http://www.python.org/doc/current/ext/intro.html">extending</a>, in which the end-user launches the Python interpreter
|
||||
executable and imports Python “extension modules” written in C++.
|
||||
Think of taking a library written in C++ and giving it a Python
|
||||
interface so Python programmers can use it. From Python, these
|
||||
modules look just like regular Python modules.</li>
|
||||
<li><a class="reference" href="http://www.python.org/doc/current/ext/embedding.html">embedding</a>, in which the end-user launches a program written
|
||||
in C++ that in turn invokes the Python interpreter as a library
|
||||
subroutine. Think of adding scriptability to an existing
|
||||
application.</li>
|
||||
</ul>
|
||||
<p>The key distinction between extending and embedding is the location
|
||||
of C++' <tt class="docutils literal"><span class="pre">main()</span></tt> function: in the Python interpreter executable,
|
||||
or in some other program, respectively. Note that even when
|
||||
embedding Python in another program, <a class="reference" href="http://www.python.org/doc/current/ext/extending-with-embedding.html">extension modules are often
|
||||
the best way to make C/C++ functionality accessible to Python
|
||||
code</a>, so the use of extension modules is really at the heart of
|
||||
both models.</p>
|
||||
<p>Except in rare cases, extension modules are built as
|
||||
dynamically-loaded libraries with a single entry point, which means
|
||||
you can change them without rebuilding either the other extension
|
||||
modules or the executable containing <tt class="docutils literal"><span class="pre">main()</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id22" id="getting-boost-python-binaries" name="getting-boost-python-binaries">3 Getting Boost.Python Binaries</a></h1>
|
||||
<p>Since Boost.Python is a separately-compiled (as opposed to
|
||||
<a class="reference" href="../../../more/getting_started/windows.html#header-only-libraries">header-only</a>) library, its user relies on the services of a
|
||||
Boost.Python library binary.</p>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id23" id="no-install-quickstart" name="no-install-quickstart">3.1 No-Install Quickstart</a></h2>
|
||||
<p>If you just want to get started quickly building and testing
|
||||
Boost.Python extension modules, or embedding Python in an
|
||||
executable, you don't need to worry about installing Boost.Python
|
||||
binaries explicitly. These instructions use <a class="reference" href="../../../tools/build">Boost.Build</a> projects,
|
||||
which will build those binaries as soon as they're needed. Your
|
||||
first tests may take a little longer while you wait for
|
||||
Boost.Python to build, but doing things this way will save you from
|
||||
worrying about build intricacies like which library binaries to use
|
||||
for a specific compiler configuration.</p>
|
||||
<div class="note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p>Of course it's possible to use other build systems to
|
||||
build Boost.Python and its extensions, but they are not
|
||||
officially supported by Boost and <strong>99% of all “I can't build
|
||||
Boost.Python” problems come from trying to use another build
|
||||
system</strong>.</p>
|
||||
<p class="last">If you want to use another system anyway, we suggest that you
|
||||
follow these instructions, and then invoke <tt class="docutils literal"><span class="pre">bjam</span></tt> with the
|
||||
<tt class="docutils literal"><span class="pre">-a</span> <span class="pre">-o</span></tt><em>filename</em> option to dump the build commands it executes
|
||||
to a file, so you can see what your build system needs to do.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id24" id="installing-boost-python-on-your-system" name="installing-boost-python-on-your-system">3.2 Installing Boost.Python on your System</a></h2>
|
||||
<p>If you need a regular, installation of the Boost.Python library
|
||||
binaries on your system, the Boost <a class="reference" href="../../../more/getting_started/index.html">Getting Started Guide</a> will
|
||||
walk you through the steps of installing one. If building binaries
|
||||
from source, you might want to supply the <tt class="docutils literal"><span class="pre">--with-python</span></tt>
|
||||
argument to <tt class="docutils literal"><span class="pre">bjam</span></tt> (or the <tt class="docutils literal"><span class="pre">--with-libraries=python</span></tt> argument
|
||||
to <tt class="docutils literal"><span class="pre">configure</span></tt>), so only the Boost.Python binary will be built,
|
||||
rather than all the Boost binaries.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id25" id="configuring-boost-build" name="configuring-boost-build">4 Configuring Boost.Build</a></h1>
|
||||
<p>As described in the <a class="reference" href="http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration">Boost.Build reference manual</a>, a file called
|
||||
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> in your home
|
||||
directory<a class="footnote-reference" href="#home-dir" id="id5" name="id5"><sup>7</sup></a> is used to
|
||||
describe the build resources available to the build system. You'll
|
||||
need to tell it about your Python installation.</p>
|
||||
<div class="admonition-users-of-unix-variant-oses admonition">
|
||||
<p class="first admonition-title">Users of Unix-Variant OSes</p>
|
||||
<p class="last">If you are using a unix-variant OS and you ran Boost's
|
||||
<tt class="docutils literal"><span class="pre">configure</span></tt> script, it may have generated a
|
||||
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> for you.<a class="footnote-reference" href="#overwrite" id="id7" name="id7"><sup>4</sup></a> If your <tt class="docutils literal"><span class="pre">configure</span></tt>/<tt class="docutils literal"><span class="pre">make</span></tt> sequence was successful and Boost.Python binaries
|
||||
were built, your <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file is probably already
|
||||
correct.</p>
|
||||
</div>
|
||||
<p>If you have a fairly “standard” python installation for your
|
||||
platform, there's very little you need to do to describe it.
|
||||
Simply having</p>
|
||||
<pre class="literal-block">
|
||||
import toolset : using ;
|
||||
using python ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
This will update all of the Boost.Python v1 test and example targets. The
|
||||
tests are relatively verbose by default. To get less-verbose output, you
|
||||
might try
|
||||
<p>in a <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file in your home directory<a class="footnote-reference" href="#home-dir" id="id8" name="id8"><sup>7</sup></a>
|
||||
should be enough.<a class="footnote-reference" href="#user-config-jam" id="id9" name="id9"><sup>6</sup></a> For more complicated setups,
|
||||
see <a class="reference" href="#advanced-configuration">Advanced Configuration</a>.</p>
|
||||
<div class="note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">You might want to pass the <tt class="docutils literal"><span class="pre">--debug-configuration</span></tt>
|
||||
option to <tt class="docutils literal"><span class="pre">bjam</span></tt> the first few times you invoke it, to make
|
||||
sure that Boost.Build is correctly locating all the parts of
|
||||
your Python installation. If it isn't, consider passing some of
|
||||
the optional <a class="reference" href="#python-configuration-parameters">Python configuration parameters</a> detailed below.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id26" id="building-an-extension-module" name="building-an-extension-module">5 Building an Extension Module</a></h1>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id27" id="testing" name="testing">6 Testing</a></h1>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id28" id="advanced-configuration" name="advanced-configuration">7 Advanced Configuration</a></h1>
|
||||
<p>If you have several versions of Python installed, or Python is
|
||||
installed in an unusual way, you may want to supply any or all of
|
||||
the following optional parameters to <tt class="docutils literal"><span class="pre">using</span> <span class="pre">python</span></tt>.</p>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id29" id="python-configuration-parameters" name="python-configuration-parameters">7.1 Python Configuration Parameters</a></h2>
|
||||
<dl class="docutils">
|
||||
<dt>version</dt>
|
||||
<dd>the version of Python to use. Should be in Major.Minor
|
||||
format, for example, <tt class="docutils literal"><span class="pre">2.3</span></tt>. Do not include the subminor
|
||||
version (i.e. <em>not</em> <tt class="docutils literal"><span class="pre">2.5.1</span></tt>). If you have multiple Python
|
||||
versions installed, the version will usually be the only
|
||||
additional argument required.</dd>
|
||||
<dt>cmd-or-prefix</dt>
|
||||
<dd>preferably, a command that invokes a Python
|
||||
interpreter. Alternatively, the installation prefix for Python
|
||||
libraries and header files. Use the alternative formulation if
|
||||
there is no appropriate Python executable available.</dd>
|
||||
<dt>includes</dt>
|
||||
<dd>the <tt class="docutils literal"><span class="pre">#include</span></tt> path for Python headers.</dd>
|
||||
<dt>libraries</dt>
|
||||
<dd>the path to Python library binaries. On MacOS/Darwin,
|
||||
you can also pass the path of the Python framework.</dd>
|
||||
<dt>condition</dt>
|
||||
<dd>if specified, should be a set of Boost.Build
|
||||
properties that are matched against the build configuration when
|
||||
Boost.Build selects a Python configuration to use.</dd>
|
||||
<dt>extension-suffix</dt>
|
||||
<dd>A string to append to the name of extension
|
||||
modules before the true filename extension. You almost certainly
|
||||
don't need to use this. Usually this suffix is only used when
|
||||
targeting a Windows debug build of Python, and will be set
|
||||
automatically for you based on the value of the
|
||||
<tt class="docutils literal"><span class="pre"><python-debugging></span></tt> feature. However, at least one Linux
|
||||
distribution (Ubuntu Feisty Fawn) has a specially configured
|
||||
<a class="reference" href="https://wiki.ubuntu.com/PyDbgBuilds">python-dbg</a> package that claims to use such a suffix.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id30" id="examples" name="examples">7.2 Examples</a></h2>
|
||||
<p>Note that in the examples below, case and <em>especially whitespace</em> are
|
||||
significant.</p>
|
||||
<ul>
|
||||
<li><p class="first">If you have both python 2.5 and python 2.4 installed,
|
||||
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> might contain:</p>
|
||||
<pre class="literal-block">
|
||||
using python : 2.5 ; # Make both versions of Python available
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS= test
|
||||
using python : 2.4 ; # To build with python 2.4, add python=2.4
|
||||
# to your command line.
|
||||
</pre>
|
||||
</blockquote>
|
||||
By default, <code>PYTHON_TEST_ARGS</code> is set to <code>-v</code>.
|
||||
|
||||
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
||||
Though there are other approaches, the smoothest and most reliable way to
|
||||
build an extension module using Boost.Python is with Boost.Build. If you
|
||||
have to use another build system, you should use Boost.Build at least
|
||||
once with the "<code><b>-n</b></code>" option so you can see the
|
||||
command-lines it uses, and replicate them. You are likely to run into
|
||||
compilation or linking problems otherwise.
|
||||
|
||||
<p>The files required to build a Boost.Python extension module using bjam
|
||||
are the "local" files <tt>Jamfile</tt>, <tt>Jamrules</tt>, and
|
||||
<tt>boost_build.jam</tt>, and the <tt>boost/</tt>
|
||||
and <tt>tools/build/v1/</tt> subdirectories of your Boost
|
||||
tree. The latter directory contains the source code of the
|
||||
Boost.Build system, which is used to generate the correct build
|
||||
commands for your extension module. The '<tt>v1</tt>' refers to
|
||||
Boost.Build version 1. Version 2 is pre-release and currently not
|
||||
ready for general use.
|
||||
|
||||
<p>
|
||||
The <tt>libs/python/example/</tt> project we're going to build is
|
||||
set up to automatically rebuild the Boost.Python library in place
|
||||
whenever it's out-of-date rather than just reusing an existing
|
||||
library, so you'll also need the Boost.Python library sources in
|
||||
<tt>boost/python/src/</tt>.
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<b>Note:</b> Third-party package and distribution maintainers
|
||||
for various operating systems sometimes split up Boost's
|
||||
structure or omit parts of it, so if you didn't download an
|
||||
official <a href=
|
||||
"http://sourceforge.net/project/showfiles.php?group_id=7586">Boost
|
||||
release</a> you might want to <a href=
|
||||
"http://cvs.sourceforge.net/viewcvs.py/boost/boost/">browse our CVS
|
||||
structure</a> to make sure you have everything you need, and in the
|
||||
right places.
|
||||
</blockquote>
|
||||
|
||||
<p>The <code>libs/python/example</code>
|
||||
subdirectory of your boost installation contains a small example which
|
||||
builds and tests two extensions. To build your own extensions copy the
|
||||
example subproject and make the following two edits:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<code><a href=
|
||||
"../example/boost-build.jam"><b>boost-build.jam</b></a></code> - edit
|
||||
the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
<p>The first version configured (2.5) becomes the default. To build
|
||||
against python 2.4, add <tt class="docutils literal"><span class="pre">python=2.4</span></tt> to the <tt class="docutils literal"><span class="pre">bjam</span></tt> command line.</p>
|
||||
</li>
|
||||
<li><p class="first">If you have python installed in an unusual location, you might
|
||||
supply the path to the interpreter in the <tt class="docutils literal"><span class="pre">cmd-or-prefix</span></tt>
|
||||
parameter:</p>
|
||||
<pre class="literal-block">
|
||||
using python : : /usr/local/python-2.6-beta/bin/python ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the <code>tools/build/v1</code>
|
||||
subdirectory of your Boost installation.
|
||||
</li>
|
||||
</li>
|
||||
<li><p class="first">If you have a separate build of Python for use with a particular
|
||||
toolset, you might supply that toolset in the <tt class="docutils literal"><span class="pre">condition</span></tt>
|
||||
parameter:</p>
|
||||
<pre class="literal-block">
|
||||
using python ; # use for most toolsets
|
||||
|
||||
<li>
|
||||
<code><a href="../example/Jamrules"><b>Jamrules</b></a></code> - edit
|
||||
the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
# Use with Intel C++ toolset
|
||||
using python
|
||||
: # version
|
||||
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
|
||||
: # includes
|
||||
: # libraries
|
||||
: <toolset>intel # condition
|
||||
;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the root directory of your Boost
|
||||
installation.
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><p class="first">You can set up your user-config.jam so a bjam built under Windows
|
||||
can build/test both Windows and <a class="reference" href="http://cygwin.com">Cygwin</a> python extensions. Just pass
|
||||
<tt class="docutils literal"><span class="pre"><target-os>cygwin</span></tt> in the <tt class="docutils literal"><span class="pre">condition</span></tt> parameter
|
||||
for the cygwin python installation:</p>
|
||||
<pre class="literal-block">
|
||||
# windows installation
|
||||
using python ;
|
||||
|
||||
<p>The instructions <a href="#testing">above</a> for testing Boost.Python
|
||||
apply equally to your new extension modules in this subproject.</p>
|
||||
# cygwin installation
|
||||
using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
|
||||
</pre>
|
||||
<p>when you put target-os=cygwin in your build request, it should build
|
||||
with the cygwin version of python:<a class="footnote-reference" href="#flavor" id="id11" name="id11"><sup>5</sup></a></p>
|
||||
<blockquote>
|
||||
<p>bjam target-os=cygwin toolset=gcc</p>
|
||||
</blockquote>
|
||||
<p>This is supposed to work the other way, too (targeting windows
|
||||
python with a <a class="reference" href="http://cygwin.com">Cygwin</a> bjam) but it seems as though the support in
|
||||
Boost.Build's toolsets for building that way is broken at the
|
||||
time of this writing.</p>
|
||||
</li>
|
||||
<li><p class="first">Note that because of <a class="reference" href="http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection">the way Boost.Build currently selects target
|
||||
alternatives</a>, you might have be very explicit in your build
|
||||
requests. For example, given:</p>
|
||||
<pre class="literal-block">
|
||||
using python : 2.5 ; # a regular windows build
|
||||
using python : 2.4 : : : : <target-os>cygwin ;
|
||||
</pre>
|
||||
<p>building with</p>
|
||||
<pre class="literal-block">
|
||||
bjam target-os=cygwin
|
||||
</pre>
|
||||
<p>will yield an error. Instead, you'll need to write:</p>
|
||||
<pre class="literal-block">
|
||||
bjam target-os=cygwin/python=2.4
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id31" id="choosing-a-boost-python-library-binary" name="choosing-a-boost-python-library-binary">8 Choosing a Boost.Python Library Binary</a></h1>
|
||||
<p>If—instead of letting Boost.Build construct and link withthe right
|
||||
libraries automatically—you choose to use a pre-built Boost.Python
|
||||
library, you'll need to think about which one to link with. The
|
||||
Boost.Python binary comes in both static and dynamic flavors. Take
|
||||
care to choose the right flavor for your application.<a class="footnote-reference" href="#naming" id="id13" name="id13"><sup>2</sup></a></p>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id32" id="the-dynamic-binary" name="the-dynamic-binary">8.1 The Dynamic Binary</a></h2>
|
||||
<p>The dynamic library is the safest and most-versatile choice:</p>
|
||||
<ul class="simple">
|
||||
<li>A single copy of the library code is used by all extension
|
||||
modules built with a given toolset.<a class="footnote-reference" href="#toolset-specific" id="id14" name="id14"><sup>3</sup></a></li>
|
||||
<li>The library contains a type conversion registry. Because one
|
||||
registry is shared among all extension modules, instances of a
|
||||
class exposed to Python in one dynamically-loaded extension
|
||||
module can be passed to functions exposed in another such module.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a class="toc-backref" href="#id33" id="the-static-binary" name="the-static-binary">8.2 The Static Binary</a></h2>
|
||||
<p>It might be appropriate to use the static Boost.Python library in
|
||||
any of the following cases:</p>
|
||||
<ul class="simple">
|
||||
<li>You are <a class="reference" href="http://www.python.org/doc/current/ext/intro.html">extending</a> python and the types exposed in your
|
||||
dynamically-loaded extension module don't need to be used by any
|
||||
other Boost.Python extension modules, and you don't care if the
|
||||
core library code is duplicated among them.</li>
|
||||
<li>You are <a class="reference" href="http://www.python.org/doc/current/ext/embedding.html">embedding</a> python in your application and either:<ul>
|
||||
<li>You are targeting a Unix variant OS other than MacOS or AIX,
|
||||
where the dynamically-loaded extension modules can “see” the
|
||||
Boost.Python library symbols that are part of the executable.</li>
|
||||
<li>Or, you have statically linked some Boost.Python extension
|
||||
modules into your application and you don't care if any
|
||||
dynamically-loaded Boost.Python extension modules are able to
|
||||
use the types exposed by your statically-linked extension
|
||||
modules (and vice-versa).</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a class="toc-backref" href="#id34" id="notes-for-mingw-and-cygwin-with-mno-cygwin-gcc-users" name="notes-for-mingw-and-cygwin-with-mno-cygwin-gcc-users">9 Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users</a></h1>
|
||||
<p>If you are using a version of Python prior to 2.4.1 with a MinGW
|
||||
prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
|
||||
create a MinGW-compatible version of the Python library; the one
|
||||
shipped with Python will only work with a Microsoft-compatible
|
||||
linker. Follow the instructions in the “Non-Microsoft” section of
|
||||
the “Building Extensions: Tips And Tricks” chapter in <a class="reference" href="http://www.python.org/doc/current/inst/index.html">Installing
|
||||
Python Modules</a> to create <tt class="docutils literal"><span class="pre">libpythonXX.a</span></tt>, where <tt class="docutils literal"><span class="pre">XX</span></tt>
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.</p>
|
||||
<hr class="docutils" />
|
||||
<table class="docutils footnote" frame="void" id="id16" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id16">[1]</a></td><td>Note that although we tested earlier versions of
|
||||
Boost.Python with Python 2.2, and we don't <em>think</em> we've done
|
||||
anything to break compatibility, this release of Boost.Python
|
||||
may not have been tested with versions of Python earlier than
|
||||
2.4, so we're not 100% sure that python 2.2 and 2.3 are
|
||||
supported.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="naming" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id13" name="naming">[2]</a></td><td><p class="first">Information about how to identify the
|
||||
static and dynamic builds of Boost.Python:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="../../../more/getting_started/windows.html#library-naming">on Windows</a></li>
|
||||
<li><a class="reference" href="../../../more/getting_started/unix-variants.html#library-naming">on Unix variants</a></li>
|
||||
</ul>
|
||||
<p class="last">Be sure to read this section even if your compiler supports
|
||||
auto-linking, as Boost.Python does not yet take advantage of
|
||||
that feature.</p>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="toolset-specific" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id14" name="toolset-specific">[3]</a></td><td>Because of the way most *nix platforms
|
||||
share symbols among dynamically-loaded objects, I'm not
|
||||
certainextension modules built with different compiler toolsets
|
||||
will always use different copies of the Boost.Python library
|
||||
when loaded into the same Python instance. Not using different
|
||||
libraries could be a good thing if the compilers have compatible
|
||||
ABIs, because extension modules built with the two libraries
|
||||
would be interoperable. Otherwise, it could spell disaster,
|
||||
since an extension module and the Boost.Python library would
|
||||
have different ideas of such things as class layout. I would
|
||||
appreciate someone doing the experiment to find out what
|
||||
happens.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="overwrite" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id7" name="overwrite">[4]</a></td><td><tt class="docutils literal"><span class="pre">configure</span></tt> overwrites the existing
|
||||
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> in your home directory
|
||||
(if any) after making a backup of the old version.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="flavor" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id11" name="flavor">[5]</a></td><td>Note that the <tt class="docutils literal"><span class="pre"><target-os>cygwin</span></tt> feature is
|
||||
different from the <tt class="docutils literal"><span class="pre"><flavor>cygwin</span></tt> subfeature of the <tt class="docutils literal"><span class="pre">gcc</span></tt>
|
||||
toolset, and you might need handle both explicitly if you also
|
||||
have a MinGW GCC installed.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="user-config-jam" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id9" name="user-config-jam">[6]</a></td><td>Create the <tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file if you don't
|
||||
already have one.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="home-dir" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="home-dir">[7]</a></td><td><em>(<a class="fn-backref" href="#id5">1</a>, <a class="fn-backref" href="#id8">2</a>)</em> <p>Windows users, your home directory can be
|
||||
found by typing:</p>
|
||||
<pre class="literal-block">
|
||||
ECHO %HOMEDRIVE%%HOMEPATH%
|
||||
</pre>
|
||||
<p class="last">into a <a class="reference" href="../../../more/getting_started/windows.html#or-build-from-the-command-prompt">Windows command prompt</a></p>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<hr class="footer" />
|
||||
<a class="reference" href="./building.rst">View document source</a>.
|
||||
Generated on: 2007-04-05 20:04 UTC.
|
||||
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
||||
|
||||
<h2><a name="variants">Build Variants</a></h2>
|
||||
Three <a href=
|
||||
"../../../tools/build/v1/build_system.htm#variants">variant</a>
|
||||
configurations of all python-related targets are supported, and can be
|
||||
selected by setting the <code><a href=
|
||||
"../../../tools/build/v1/build_system.htm#user_globals">BUILD</a></code>
|
||||
variable:
|
||||
|
||||
<ul>
|
||||
<li><code>release</code> (optimization, <tt>-DNDEBUG</tt>)</li>
|
||||
|
||||
<li><code>debug</code> (no optimization <tt>-D_DEBUG</tt>)</li>
|
||||
|
||||
<li><code>debug-python</code> (no optimization, <tt>-D_DEBUG
|
||||
-DBOOST_DEBUG_PYTHON</tt>)</li>
|
||||
</ul>
|
||||
|
||||
<p>The first two variants of the <code>boost_python</code> library are
|
||||
built by default, and are compatible with the default Python
|
||||
distribution. The <code>debug-python</code> variant corresponds to a
|
||||
specially-built debugging version of Python. On *nix platforms, this
|
||||
python is built by adding <code>--with-pydebug</code> when configuring
|
||||
the Python build. On Windows, the debugging version of Python is
|
||||
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
|
||||
Visual C++ 6.0 project in the <code>PCBuild</code> subdirectory of your
|
||||
Python distribution. Extension modules built with Python debugging
|
||||
enabled are <b>not link-compatible</b> with a non-debug build of Python.
|
||||
Since few people actually have a debug build of Python (it doesn't come
|
||||
with the standard distribution), the normal <code>debug</code> variant
|
||||
builds modules which are compatible with ordinary Python.</p>
|
||||
|
||||
<p>On many windows compilers, when extension modules are built with
|
||||
<tt>-D_DEBUG</tt>, Python defaults to <i>force</i> linking with a special
|
||||
debugging version of the Python DLL. Since this debug DLL isn't supplied
|
||||
with the default Python installation for Windows, Boost.Python uses
|
||||
<tt><a href=
|
||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a></tt>
|
||||
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is
|
||||
<tt>#include</tt>d - unless <code>BOOST_DEBUG_PYTHON</code> is
|
||||
defined.</p>
|
||||
|
||||
<p>If you want the extra runtime checks available with the debugging
|
||||
version of the library, <tt>#define BOOST_DEBUG_PYTHON</tt> to re-enable
|
||||
python debuggin, and link with the <code>debug-python</code> variant of
|
||||
<tt>boost_python</tt>.</p>
|
||||
|
||||
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that any
|
||||
source files in your extension module <tt>#include <<a href=
|
||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
||||
instead of the usual <tt>Python.h</tt>, or you will have link
|
||||
incompatibilities.<br>
|
||||
</p>
|
||||
|
||||
<h2><a name="VisualStudio">Building Using the Microsoft Visual Studio
|
||||
IDE</a></h2>
|
||||
|
||||
<p>For the those of you who feel more comfortable in the IDE world, a
|
||||
workspace and project file have been included in the <code>
|
||||
libs/python/build/VisualStudio</code> subdirectory.
|
||||
It builds release and debug versions of the Boost.Python libraries and
|
||||
places them and the same directory as Jamfile build does, though the
|
||||
intermediate object files are placed in a different directory. The files
|
||||
have been created using Microsoft Visual C++ version 6, but they should
|
||||
work for later versions as well. You will need to tell the IDE where to
|
||||
find the Python <code>Include/</code> and <code>Libs/</code> directories.
|
||||
Under <b>Tools>Options>Directories</b>, add an entry for the Python
|
||||
include dir (i.e. <code>c:/Python22/Include</code>), and one for the Lib
|
||||
(i.e. <code>c:/Python/Libs</code>. Make sure it is <code>Libs</code> with
|
||||
an "<code>s</code>" and not just <code>Lib</code>).</p>
|
||||
|
||||
<h3>Using the IDE for your own projects</h3>
|
||||
|
||||
<p>Building your own projects using the IDE is slightly more complicated.
|
||||
Firstly, you need to make sure that the project you create as the right
|
||||
kind. It should be a "Win32 Dynamic-Link Library". The default one that
|
||||
Visual Studio 6 creates needs some modifications: turn on RTTI, and
|
||||
change the debug and release builds to use the respective debug and
|
||||
release Multithreaded DLL versions. You should probably turn off
|
||||
incremental linking too -- I believe it a bit flaky. If you do this, then
|
||||
change the "Debug Info" to "Program Database" to get rid of the Edit and
|
||||
Continue warning.</p>
|
||||
|
||||
<p>You'll need to add the Boost root directory under
|
||||
<b>Tools>Options>Directories</b> to get your code compiling. To
|
||||
make it link, add the above <code>boost_python.dsp</code> file to your
|
||||
workspace, and make your project depend upon it (under
|
||||
<b>Project>Dependencies</b>). You should be able to build now.</p>
|
||||
|
||||
<p>Lastly, go to the <b>Project Settings>Debug</b> Page and add the
|
||||
<code>Python.exe</code> as the executable for the project. Set a startup
|
||||
directory, and make sure that your current project's output dll, the
|
||||
<code>boost_python.dll</code> and the <code>python22.dll</code> are on
|
||||
the current <code>PATH</code>. If you have a python script that tests
|
||||
your dll, then add it in the "Program Arguments". Now, if all went well,
|
||||
you should be able to hit the Run (F5) button, and debug your code.</p>
|
||||
|
||||
<blockquote>
|
||||
<em>The Visual Studio project files are graciously contributed and
|
||||
maintained by <a href="mailto:brett.calcott@gmail.com">Brett
|
||||
Calcott</a></em>.
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<p>© Copyright David Abrahams 2002-2004. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided
|
||||
this copyright notice appears in all copies. This document is
|
||||
provided ``as is'' without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose.</p>
|
||||
|
||||
<p>Updated: 13 April 2004 (David Abrahams)</p>
|
||||
</body>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
404
doc/building.rst
Normal file
404
doc/building.rst
Normal file
@@ -0,0 +1,404 @@
|
||||
.. 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)
|
||||
|
||||
==============================================
|
||||
|(logo)|__ Boost.Python Build and Test HOWTO
|
||||
==============================================
|
||||
|
||||
.. |(logo)| image:: ../boost.png
|
||||
:alt: Boost C++ Libraries:
|
||||
:class: boost-logo
|
||||
|
||||
__ ../index.htm
|
||||
|
||||
|
||||
.. section-numbering::
|
||||
:depth: 2
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:class: sidebar small
|
||||
|
||||
.. |newer| replace:: *newer*
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
Boost.Python requires `Python 2.2`_ [#2.2]_ *or* |newer|__.
|
||||
|
||||
.. _Python 2.2: http://www.python.org/2.2
|
||||
__ http://www.python.org
|
||||
|
||||
No-Install Quickstart
|
||||
=====================
|
||||
|
||||
There is no need to install Boost in order to get started using
|
||||
Boost.Python. These instructions use Boost.Build_ projects,
|
||||
which will build those binaries as soon as they're needed. Your
|
||||
first tests may take a little longer while you wait for
|
||||
Boost.Python to build, but doing things this way will save you from
|
||||
worrying about build intricacies like which library binaries to use
|
||||
for a specific compiler configuration.
|
||||
|
||||
.. Note:: Of course it's possible to use other build systems to
|
||||
build Boost.Python and its extensions, but they are not
|
||||
officially supported by Boost. Moreover **99% of all “I can't
|
||||
build Boost.Python” problems come from trying to use another
|
||||
build system**.
|
||||
|
||||
If you want to use another system anyway, we suggest that you
|
||||
follow these instructions, and then invoke ``bjam`` with the
|
||||
``-a -o``\ *filename* option to dump the build commands it executes
|
||||
to a file, so you can see what your build system needs to do.
|
||||
|
||||
1. Get Boost; see sections 1 and 2 of the Boost `Getting Started Guide`_.
|
||||
2. Get the ``bjam`` build driver. See sections 5.2.1-5.2.3 of the
|
||||
Boost `Getting Started Guide`_.
|
||||
3. cd into the ``libs/python/test/example`` directory.
|
||||
|
||||
.. _Getting Started Guide: ../../../more/getting_started/index.html
|
||||
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
There are two basic models for combining C++ and Python:
|
||||
|
||||
- extending_, in which the end-user launches the Python interpreter
|
||||
executable and imports Python “extension modules” written in C++.
|
||||
Think of taking a library written in C++ and giving it a Python
|
||||
interface so Python programmers can use it. From Python, these
|
||||
modules look just like regular Python modules.
|
||||
|
||||
- embedding_, in which the end-user launches a program written
|
||||
in C++ that in turn invokes the Python interpreter as a library
|
||||
subroutine. Think of adding scriptability to an existing
|
||||
application.
|
||||
|
||||
.. _extending: http://www.python.org/doc/current/ext/intro.html
|
||||
.. _embedding: http://www.python.org/doc/current/ext/embedding.html
|
||||
|
||||
The key distinction between extending and embedding is the location
|
||||
of C++' ``main()`` function: in the Python interpreter executable,
|
||||
or in some other program, respectively. Note that even when
|
||||
embedding Python in another program, `extension modules are often
|
||||
the best way to make C/C++ functionality accessible to Python
|
||||
code`__, so the use of extension modules is really at the heart of
|
||||
both models.
|
||||
|
||||
__ http://www.python.org/doc/current/ext/extending-with-embedding.html
|
||||
|
||||
Except in rare cases, extension modules are built as
|
||||
dynamically-loaded libraries with a single entry point, which means
|
||||
you can change them without rebuilding either the other extension
|
||||
modules or the executable containing ``main()``.
|
||||
|
||||
Getting Boost.Python Binaries
|
||||
=============================
|
||||
|
||||
Since Boost.Python is a separately-compiled (as opposed to
|
||||
`header-only`_) library, its user relies on the services of a
|
||||
Boost.Python library binary.
|
||||
|
||||
.. _header-only: ../../../more/getting_started/windows.html#header-only-libraries
|
||||
|
||||
Installing Boost.Python on your System
|
||||
--------------------------------------
|
||||
|
||||
If you need a regular, installation of the Boost.Python library
|
||||
binaries on your system, the Boost `Getting Started Guide`_ will
|
||||
walk you through the steps of installing one. If building binaries
|
||||
from source, you might want to supply the ``--with-python``
|
||||
argument to ``bjam`` (or the ``--with-libraries=python`` argument
|
||||
to ``configure``), so only the Boost.Python binary will be built,
|
||||
rather than all the Boost binaries.
|
||||
|
||||
Configuring Boost.Build
|
||||
=======================
|
||||
|
||||
As described in the `Boost.Build reference manual`__, a file called
|
||||
``user-config.jam`` in your home
|
||||
directory [#home-dir]_ is used to
|
||||
describe the build resources available to the build system. You'll
|
||||
need to tell it about your Python installation.
|
||||
|
||||
__ http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration
|
||||
|
||||
.. Admonition:: Users of Unix-Variant OSes
|
||||
|
||||
If you are using a unix-variant OS and you ran Boost's
|
||||
``configure`` script, it may have generated a
|
||||
``user-config.jam`` for you. [#overwrite]_ If your ``configure``\
|
||||
/\ ``make`` sequence was successful and Boost.Python binaries
|
||||
were built, your ``user-config.jam`` file is probably already
|
||||
correct.
|
||||
|
||||
If you have a fairly “standard” python installation for your
|
||||
platform, there's very little you need to do to describe it.
|
||||
Simply having ::
|
||||
|
||||
|
||||
import toolset : using ;
|
||||
using python ;
|
||||
|
||||
in a ``user-config.jam`` file in your home directory [#home-dir]_
|
||||
should be enough. [#user-config.jam]_ For more complicated setups,
|
||||
see `Advanced Configuration`_.
|
||||
|
||||
.. Note:: You might want to pass the ``--debug-configuration``
|
||||
option to ``bjam`` the first few times you invoke it, to make
|
||||
sure that Boost.Build is correctly locating all the parts of
|
||||
your Python installation. If it isn't, consider passing some of
|
||||
the optional `Python configuration parameters`_ detailed below.
|
||||
|
||||
Building an Extension Module
|
||||
============================
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
|
||||
Advanced Configuration
|
||||
======================
|
||||
|
||||
If you have several versions of Python installed, or Python is
|
||||
installed in an unusual way, you may want to supply any or all of
|
||||
the following optional parameters to ``using python``.
|
||||
|
||||
Python Configuration Parameters
|
||||
-------------------------------
|
||||
|
||||
version
|
||||
the version of Python to use. Should be in Major.Minor
|
||||
format, for example, ``2.3``. Do not include the subminor
|
||||
version (i.e. *not* ``2.5.1``). If you have multiple Python
|
||||
versions installed, the version will usually be the only
|
||||
additional argument required.
|
||||
|
||||
cmd-or-prefix
|
||||
preferably, a command that invokes a Python
|
||||
interpreter. Alternatively, the installation prefix for Python
|
||||
libraries and header files. Use the alternative formulation if
|
||||
there is no appropriate Python executable available.
|
||||
|
||||
includes
|
||||
the ``#include`` path for Python headers.
|
||||
|
||||
libraries
|
||||
the path to Python library binaries. On MacOS/Darwin,
|
||||
you can also pass the path of the Python framework.
|
||||
|
||||
condition
|
||||
if specified, should be a set of Boost.Build
|
||||
properties that are matched against the build configuration when
|
||||
Boost.Build selects a Python configuration to use.
|
||||
|
||||
extension-suffix
|
||||
A string to append to the name of extension
|
||||
modules before the true filename extension. You almost certainly
|
||||
don't need to use this. Usually this suffix is only used when
|
||||
targeting a Windows debug build of Python, and will be set
|
||||
automatically for you based on the value of the
|
||||
``<python-debugging>`` feature. However, at least one Linux
|
||||
distribution (Ubuntu Feisty Fawn) has a specially configured
|
||||
`python-dbg`__ package that claims to use such a suffix.
|
||||
|
||||
__ https://wiki.ubuntu.com/PyDbgBuilds
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Note that in the examples below, case and *especially whitespace* are
|
||||
significant.
|
||||
|
||||
- If you have both python 2.5 and python 2.4 installed,
|
||||
``user-config.jam`` might contain::
|
||||
|
||||
using python : 2.5 ; # Make both versions of Python available
|
||||
|
||||
using python : 2.4 ; # To build with python 2.4, add python=2.4
|
||||
# to your command line.
|
||||
|
||||
The first version configured (2.5) becomes the default. To build
|
||||
against python 2.4, add ``python=2.4`` to the ``bjam`` command line.
|
||||
|
||||
- If you have python installed in an unusual location, you might
|
||||
supply the path to the interpreter in the ``cmd-or-prefix``
|
||||
parameter::
|
||||
|
||||
using python : : /usr/local/python-2.6-beta/bin/python ;
|
||||
|
||||
- If you have a separate build of Python for use with a particular
|
||||
toolset, you might supply that toolset in the ``condition``
|
||||
parameter::
|
||||
|
||||
using python ; # use for most toolsets
|
||||
|
||||
# Use with Intel C++ toolset
|
||||
using python
|
||||
: # version
|
||||
: c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
|
||||
: # includes
|
||||
: # libraries
|
||||
: <toolset>intel # condition
|
||||
;
|
||||
|
||||
- You can set up your user-config.jam so a bjam built under Windows
|
||||
can build/test both Windows and Cygwin_ python extensions. Just pass
|
||||
``<target-os>cygwin`` in the ``condition`` parameter
|
||||
for the cygwin python installation::
|
||||
|
||||
# windows installation
|
||||
using python ;
|
||||
|
||||
# cygwin installation
|
||||
using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
|
||||
|
||||
when you put target-os=cygwin in your build request, it should build
|
||||
with the cygwin version of python: [#flavor]_
|
||||
|
||||
bjam target-os=cygwin toolset=gcc
|
||||
|
||||
This is supposed to work the other way, too (targeting windows
|
||||
python with a Cygwin_ bjam) but it seems as though the support in
|
||||
Boost.Build's toolsets for building that way is broken at the
|
||||
time of this writing.
|
||||
|
||||
- Note that because of `the way Boost.Build currently selects target
|
||||
alternatives`__, you might have be very explicit in your build
|
||||
requests. For example, given::
|
||||
|
||||
using python : 2.5 ; # a regular windows build
|
||||
using python : 2.4 : : : : <target-os>cygwin ;
|
||||
|
||||
building with ::
|
||||
|
||||
bjam target-os=cygwin
|
||||
|
||||
will yield an error. Instead, you'll need to write::
|
||||
|
||||
bjam target-os=cygwin/python=2.4
|
||||
|
||||
.. _Cygwin: http://cygwin.com
|
||||
|
||||
__ http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection
|
||||
|
||||
Choosing a Boost.Python Library Binary
|
||||
======================================
|
||||
|
||||
If—instead of letting Boost.Build construct and link withthe right
|
||||
libraries automatically—you choose to use a pre-built Boost.Python
|
||||
library, you'll need to think about which one to link with. The
|
||||
Boost.Python binary comes in both static and dynamic flavors. Take
|
||||
care to choose the right flavor for your application. [#naming]_
|
||||
|
||||
The Dynamic Binary
|
||||
------------------
|
||||
|
||||
The dynamic library is the safest and most-versatile choice:
|
||||
|
||||
- A single copy of the library code is used by all extension
|
||||
modules built with a given toolset. [#toolset-specific]_
|
||||
|
||||
- The library contains a type conversion registry. Because one
|
||||
registry is shared among all extension modules, instances of a
|
||||
class exposed to Python in one dynamically-loaded extension
|
||||
module can be passed to functions exposed in another such module.
|
||||
|
||||
The Static Binary
|
||||
-----------------
|
||||
|
||||
It might be appropriate to use the static Boost.Python library in
|
||||
any of the following cases:
|
||||
|
||||
- You are extending_ python and the types exposed in your
|
||||
dynamically-loaded extension module don't need to be used by any
|
||||
other Boost.Python extension modules, and you don't care if the
|
||||
core library code is duplicated among them.
|
||||
|
||||
- You are embedding_ python in your application and either:
|
||||
|
||||
- You are targeting a Unix variant OS other than MacOS or AIX,
|
||||
where the dynamically-loaded extension modules can “see” the
|
||||
Boost.Python library symbols that are part of the executable.
|
||||
|
||||
- Or, you have statically linked some Boost.Python extension
|
||||
modules into your application and you don't care if any
|
||||
dynamically-loaded Boost.Python extension modules are able to
|
||||
use the types exposed by your statically-linked extension
|
||||
modules (and vice-versa).
|
||||
|
||||
Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users
|
||||
=======================================================
|
||||
|
||||
If you are using a version of Python prior to 2.4.1 with a MinGW
|
||||
prior to 3.0.0 (with binutils-2.13.90-20030111-1), you will need to
|
||||
create a MinGW-compatible version of the Python library; the one
|
||||
shipped with Python will only work with a Microsoft-compatible
|
||||
linker. Follow the instructions in the “Non-Microsoft” section of
|
||||
the “Building Extensions: Tips And Tricks” chapter in `Installing
|
||||
Python Modules`__ to create ``libpythonXX.a``, where ``XX``
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.
|
||||
|
||||
__ http://www.python.org/doc/current/inst/index.html
|
||||
|
||||
-----------------------------
|
||||
|
||||
.. [#2.2] Note that although we tested earlier versions of
|
||||
Boost.Python with Python 2.2, and we don't *think* we've done
|
||||
anything to break compatibility, this release of Boost.Python
|
||||
may not have been tested with versions of Python earlier than
|
||||
2.4, so we're not 100% sure that python 2.2 and 2.3 are
|
||||
supported.
|
||||
|
||||
.. [#naming] Information about how to identify the
|
||||
static and dynamic builds of Boost.Python:
|
||||
|
||||
* `on Windows`__
|
||||
* `on Unix variants`__
|
||||
|
||||
__ ../../../more/getting_started/windows.html#library-naming
|
||||
__ ../../../more/getting_started/unix-variants.html#library-naming
|
||||
|
||||
Be sure to read this section even if your compiler supports
|
||||
auto-linking, as Boost.Python does not yet take advantage of
|
||||
that feature.
|
||||
|
||||
.. [#toolset-specific] Because of the way most \*nix platforms
|
||||
share symbols among dynamically-loaded objects, I'm not
|
||||
certainextension modules built with different compiler toolsets
|
||||
will always use different copies of the Boost.Python library
|
||||
when loaded into the same Python instance. Not using different
|
||||
libraries could be a good thing if the compilers have compatible
|
||||
ABIs, because extension modules built with the two libraries
|
||||
would be interoperable. Otherwise, it could spell disaster,
|
||||
since an extension module and the Boost.Python library would
|
||||
have different ideas of such things as class layout. I would
|
||||
appreciate someone doing the experiment to find out what
|
||||
happens.
|
||||
|
||||
.. [#overwrite] ``configure`` overwrites the existing
|
||||
``user-config.jam`` in your home directory
|
||||
(if any) after making a backup of the old version.
|
||||
|
||||
.. [#flavor] Note that the ``<target-os>cygwin`` feature is
|
||||
different from the ``<flavor>cygwin`` subfeature of the ``gcc``
|
||||
toolset, and you might need handle both explicitly if you also
|
||||
have a MinGW GCC installed.
|
||||
|
||||
.. [#user-config.jam] Create the ``user-config.jam`` file if you don't
|
||||
already have one.
|
||||
|
||||
.. [#home-dir] Windows users, your home directory can be
|
||||
found by typing::
|
||||
|
||||
ECHO %HOMEDRIVE%%HOMEPATH%
|
||||
|
||||
into a `Windows command prompt`__
|
||||
|
||||
__ ../../../more/getting_started/windows.html#or-build-from-the-command-prompt
|
||||
@@ -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="id2632684"></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="id2595112"></a>
|
||||
Hello World
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A
|
||||
C++ Function:
|
||||
@@ -135,14 +132,20 @@
|
||||
</pre>
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module
|
||||
from start to finish...</b></span></em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Next stop... Building your Hello World
|
||||
module from start to finish...</strong></span></em></span>
|
||||
</p>
|
||||
<p>
|
||||
</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:46:01 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="id2654982"></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,295 +81,171 @@ 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="id2655076"></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="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>
|
||||
</p>
|
||||
</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>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<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>
|
||||
<p>
|
||||
</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
|
||||
in Python, the Python<span class="emphasis"><em>C API requires you to do it [@http:</em></span>/www.python.org/doc/current/api/refcounts.html
|
||||
by hand]. This is messy and especially hard to get right in the presence
|
||||
of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a>
|
||||
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
|
||||
automate the process.
|
||||
</p>
|
||||
<a name="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
|
||||
<a name="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="id2655255"></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="id2655783"></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="id2656116"></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
|
||||
can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a>
|
||||
to print the exception's traceback to the console, or comparing the type
|
||||
of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
|
||||
handling functions</a> of the Python<span class="emphasis"><em>C API in your catch-statement.
|
||||
This can be as simple as calling [@http:</em></span>/www.python.org/doc/api/exceptionHandling.html#l2h-70
|
||||
PyErr_Print()] to print the exception's traceback to the console, or comparing
|
||||
the type of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
|
||||
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 +262,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,25 @@
|
||||
<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="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>.
|
||||
</p>
|
||||
</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,22 +400,25 @@
|
||||
<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>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
|
||||
<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,19 @@
|
||||
<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>.
|
||||
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>
|
||||
<p class="blurb">
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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 <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>.
|
||||
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>.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Finally, exposing:
|
||||
</p>
|
||||
@@ -474,10 +482,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 +501,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 +518,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="id2646169"></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 +561,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="id2646853"></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,14 +596,17 @@
|
||||
<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>.
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
|
||||
@@ -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%">
|
||||
@@ -41,12 +38,18 @@
|
||||
see facilities that will make it even easier for us to expose C++ functions
|
||||
that take advantage of C++ features such as overloading and default arguments.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em>Read on...</em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em>Read on...</em></span>
|
||||
</p>
|
||||
<p>
|
||||
</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 +68,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!
|
||||
@@ -93,9 +96,9 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
Here's an example where it didn't
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">y</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
|
||||
</pre>
|
||||
<p>
|
||||
What's the problem?
|
||||
@@ -123,19 +126,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,16 +168,16 @@ 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">
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> # <span class="identifier">Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||
<span class="special">>>></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>
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> <span class="preprocessor"># Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||
<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="preprocessor"># 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 +191,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="id2648560"></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 +226,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,42 +263,45 @@ 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>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.overloading"></a>Overloading</h3></div></div></div>
|
||||
@@ -356,21 +362,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 +410,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="id2650414"></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 +431,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="id2650701"></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 +452,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 +473,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 +486,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="id2651031"></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 +509,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 +517,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 +560,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="id2651734"></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,29 @@
|
||||
<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="id2595436"></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>.
|
||||
every boost distribution: <span class="bold"><strong>bjam</strong></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>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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 <tt class="literal">bjam</tt>.<br>
|
||||
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.
|
||||
</p>
|
||||
</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 +78,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 +90,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="id2595623"></a>
|
||||
Let's Jam!
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
|
||||
</p>
|
||||
@@ -123,13 +123,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 +139,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,20 +151,26 @@ 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="id2595752"></a>
|
||||
Running bjam
|
||||
</h2>
|
||||
</h3>
|
||||
<p>
|
||||
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
|
||||
interpreter.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Start it up.
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
Start it up.
|
||||
</p>
|
||||
<p>
|
||||
</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 +183,24 @@ 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
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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.
|
||||
</p>
|
||||
</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 +263,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
|
||||
@@ -273,9 +282,15 @@ b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
</pre>
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="bold"><b>There you go... Have fun!</b></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>There you go... Have fun!</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
|
||||
@@ -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,18 @@
|
||||
<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.
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Python:
|
||||
</p>
|
||||
@@ -198,12 +198,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="id2653534"></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 +225,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 +243,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 +260,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 +273,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 +293,19 @@
|
||||
</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>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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>.
|
||||
</p>
|
||||
</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,18 @@
|
||||
<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>.
|
||||
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>
|
||||
<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
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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 <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt>
|
||||
your system, like <code class="literal">.so</code> for Unix and <code class="literal">.dll</code>
|
||||
for Windows, works just as well.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:
|
||||
</p>
|
||||
@@ -115,12 +115,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 +159,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>
|
||||
@@ -167,12 +167,12 @@
|
||||
__init__.py
|
||||
core/
|
||||
__init__.py
|
||||
_core.pyd
|
||||
<span class="underline">core.pyd
|
||||
filters/
|
||||
__init__.py
|
||||
_filters.pyd
|
||||
\</span>_init__.py
|
||||
<span class="underline">filters.pyd
|
||||
io/
|
||||
__init__.py
|
||||
\</span>_init__.py
|
||||
_io.pyd
|
||||
</pre>
|
||||
<p>
|
||||
@@ -187,11 +187,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 +208,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 +222,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 +263,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 +277,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 +292,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 +391,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,12 +427,17 @@
|
||||
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">
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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
|
||||
take a look at the <code class="literal">--multiple</code> option, that generates the
|
||||
wrappers in various files as demonstrated here.
|
||||
</p>
|
||||
<p class="blurb">
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<p class="title"><b></b></p>
|
||||
<p>
|
||||
<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
|
||||
@@ -440,6 +445,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
|
||||
@@ -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,
|
||||
@@ -109,7 +127,7 @@ void greet()
|
||||
|
||||
// Define greet function in Python.
|
||||
object result = exec(
|
||||
"def greet(self): \n"
|
||||
"def greet(): \n"
|
||||
" return 'Hello from Python!' \n",
|
||||
global, global);
|
||||
|
||||
@@ -126,7 +144,7 @@ void greet()
|
||||
we could also store it in an a file...</para>
|
||||
|
||||
<pre>
|
||||
def greet(self):
|
||||
def greet():
|
||||
return 'Hello from Python!'
|
||||
</pre>
|
||||
<para>... and execute that instead.</para>
|
||||
|
||||
@@ -214,6 +214,9 @@ namespace boost { namespace python { namespace self_ns {
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> str(self_t);
|
||||
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> repr(self_t);
|
||||
|
||||
}}};
|
||||
</pre>
|
||||
The tables below describe the methods generated when the results of the
|
||||
@@ -765,6 +768,15 @@ namespace boost { namespace python { namespace self_ns {
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>repr</code></td>
|
||||
|
||||
<td><code>__repr__</code></td>
|
||||
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="other-spec"></a>Class Template <code>other</code></h3>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# 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)
|
||||
|
||||
project : requirements <library>/boost/python//boost_python ;
|
||||
|
||||
python-extension getting_started1 : getting_started1.cpp ;
|
||||
|
||||
bpl-test test1
|
||||
: # Python test driver
|
||||
test_getting_started1.py
|
||||
# extension modules to use
|
||||
getting_started1 ;
|
||||
|
||||
|
||||
python-extension getting_started2 : getting_started2.cpp ;
|
||||
|
||||
bpl-test test2
|
||||
: # Python test driver
|
||||
test_getting_started2.py
|
||||
# extension modules to use
|
||||
getting_started2 ;
|
||||
|
||||
python-extension std_pair : std_pair.cpp ;
|
||||
|
||||
bpl-test test3
|
||||
: # Python test driver
|
||||
test_std_pair.py
|
||||
# extension modules to use
|
||||
std_pair_ext ;
|
||||
|
||||
# Don't run tests by default
|
||||
explicit test1 test2 test3 ;
|
||||
alias test : test1 test2 test3 ;
|
||||
explicit test ;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# If you move this example from its place in the Boost tree, edit this
|
||||
# path to point at the root directory of your Boost installation (the
|
||||
# one containing a subdirectory called "boost/" and a sub-subdirectory
|
||||
# "boost/python/" full of .hpp files). Absolute paths work, too.
|
||||
#
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
|
||||
# Boost.Python configuration variables, as described in
|
||||
# http://www.boost.org/libs/python/doc/building.html#configuration.
|
||||
# Usually you don't need to set these; the defaults will work. If you
|
||||
# do set them, try to change as few of them as possible, starting with
|
||||
# the first ones.
|
||||
|
||||
# PYTHON_VERSION = <the two-part Major.Minor version number, e.g. 2.2> ;
|
||||
# PYTHON_ROOT = <root directory of your Python installation, e.g. /usr> ;
|
||||
# PYTHON_INCLUDES = <path to Python #include directories> ;
|
||||
# PYTHON_LIB_PATH = <path to Python library object> ;
|
||||
|
||||
# You may need to configure your compiler toolset, especially if you
|
||||
# want to build with a compiler that is not the "system default" or if
|
||||
# it is installed in a nonstandard place; see
|
||||
# http://www.boost.org/more/getting_started.html#Configuring for
|
||||
# details.
|
||||
|
||||
# Makes a project id for boost so that other Boost.Build projects can
|
||||
# refer to it by name.
|
||||
#
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
|
||||
# Change this setting to have all your built products placed under a
|
||||
# single directory:
|
||||
#
|
||||
# ALL_LOCATE_TARGET = <root directory for all built products>
|
||||
@@ -34,6 +34,7 @@ struct BOOST_PYTHON_DECL registration
|
||||
{
|
||||
public: // member functions
|
||||
explicit registration(type_info target, bool is_shared_ptr = false);
|
||||
~registration();
|
||||
|
||||
// Convert the appropriately-typed data to Python
|
||||
PyObject* to_python(void const volatile*) const;
|
||||
|
||||
@@ -47,7 +47,8 @@ enum operator_id
|
||||
op_ixor,
|
||||
op_ior,
|
||||
op_complex,
|
||||
op_nonzero
|
||||
op_nonzero,
|
||||
op_repr
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
# if defined(_SGI_COMPILER_VERSION) && _SGI_COMPILER_VERSION >= 740
|
||||
# undef _POSIX_C_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
# undef HAVE_STDINT_H // undo Python 2.5.1 define
|
||||
# endif
|
||||
|
||||
//
|
||||
|
||||
@@ -13,18 +13,25 @@ namespace boost
|
||||
namespace python
|
||||
{
|
||||
|
||||
// Evaluate python expression from str.
|
||||
// global and local are the global and local scopes respectively,
|
||||
// used during evaluation.
|
||||
object
|
||||
BOOST_PYTHON_DECL
|
||||
eval(str string, object global = object(), object local = object());
|
||||
|
||||
// Execute python source code from str.
|
||||
// global and local are the global and local scopes respectively,
|
||||
// used during execution.
|
||||
object
|
||||
BOOST_PYTHON_DECL
|
||||
BOOST_PYTHON_DECL
|
||||
exec(str string, object global = object(), object local = object());
|
||||
|
||||
// Execute python source code from file filename.
|
||||
// global and local are the global and local scopes respectively,
|
||||
// used during execution.
|
||||
object
|
||||
BOOST_PYTHON_DECL
|
||||
BOOST_PYTHON_DECL
|
||||
exec_file(str filename, object global = object(), object local = object());
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# include <boost/mpl/int.hpp>
|
||||
# include <boost/mpl/push_front.hpp>
|
||||
# include <boost/mpl/pop_front.hpp>
|
||||
# include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -103,12 +104,14 @@ namespace detail
|
||||
|
||||
// If the BasePolicy_ supplied a result converter it would be
|
||||
// ignored; issue an error if it's not the default.
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_same<
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(is_same<
|
||||
typename BasePolicy_::result_converter
|
||||
, default_result_converter
|
||||
>::value
|
||||
));
|
||||
>::value)
|
||||
, MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
|
||||
, (typename BasePolicy_::result_converter)
|
||||
);
|
||||
|
||||
typedef constructor_result_converter result_converter;
|
||||
typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright Gottfried Ganßauge 2003..2006
|
||||
// Copyright Gottfried Ganßauge 2003..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)
|
||||
|
||||
@@ -347,6 +347,7 @@ BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
|
||||
# undef BOOST_PYTHON_UNARY_OPERATOR
|
||||
|
||||
}} // namespace boost::python
|
||||
@@ -358,6 +359,7 @@ using boost::python::self_ns::long_;
|
||||
using boost::python::self_ns::float_;
|
||||
using boost::python::self_ns::complex_;
|
||||
using boost::python::self_ns::str;
|
||||
using boost::python::self_ns::repr;
|
||||
using boost::python::self_ns::pow;
|
||||
# endif
|
||||
|
||||
|
||||
@@ -57,6 +57,24 @@ BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source)
|
||||
: this->m_to_python(const_cast<void*>(source));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template< typename T >
|
||||
void delete_node( T* node )
|
||||
{
|
||||
if( !!node && !!node->next )
|
||||
delete_node( node->next );
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
registration::~registration()
|
||||
{
|
||||
delete_node(lvalue_chain);
|
||||
delete_node(rvalue_chain);
|
||||
}
|
||||
|
||||
|
||||
namespace // <unnamed>
|
||||
{
|
||||
typedef registration entry;
|
||||
|
||||
@@ -13,6 +13,15 @@ namespace boost
|
||||
namespace python
|
||||
{
|
||||
|
||||
object BOOST_PYTHON_DECL eval(str string, object global, object local)
|
||||
{
|
||||
// should be 'char const *' but older python versions don't use 'const' yet.
|
||||
char *s = python::extract<char *>(string);
|
||||
PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr());
|
||||
if (!result) throw_error_already_set();
|
||||
return object(detail::new_reference(result));
|
||||
}
|
||||
|
||||
object BOOST_PYTHON_DECL exec(str string, object global, object local)
|
||||
{
|
||||
// should be 'char const *' but older python versions don't use 'const' yet.
|
||||
|
||||
@@ -532,6 +532,10 @@ namespace objects
|
||||
if (scope().ptr() != Py_None)
|
||||
scope().attr(name) = result;
|
||||
|
||||
// For pickle. Will lead to informative error messages if pickling
|
||||
// is not enabled.
|
||||
result.attr("__reduce__") = object(make_instance_reduce_function());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -629,7 +633,6 @@ namespace objects
|
||||
|
||||
void class_base::enable_pickling_(bool getstate_manages_dict)
|
||||
{
|
||||
setattr("__reduce__", object(make_instance_reduce_function()));
|
||||
setattr("__safe_for_unpickling__", object(true));
|
||||
|
||||
if (getstate_manages_dict)
|
||||
|
||||
@@ -32,10 +32,11 @@ extern "C"
|
||||
{
|
||||
static PyObject* enum_repr(PyObject* self_)
|
||||
{
|
||||
const char *mod = PyString_AsString(PyObject_GetAttrString( self_, "__module__"));
|
||||
enum_object* self = downcast<enum_object>(self_);
|
||||
if (!self->name)
|
||||
{
|
||||
return PyString_FromFormat("%s(%ld)", self_->ob_type->tp_name, PyInt_AS_LONG(self_));
|
||||
return PyString_FromFormat("%s.%s(%ld)", mod, self_->ob_type->tp_name, PyInt_AS_LONG(self_));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -43,7 +44,7 @@ extern "C"
|
||||
if (name == 0)
|
||||
return 0;
|
||||
|
||||
return PyString_FromFormat("%s.%s", self_->ob_type->tp_name, name);
|
||||
return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +142,9 @@ namespace
|
||||
|
||||
object module_name = module_prefix();
|
||||
if (module_name)
|
||||
module_name += '.';
|
||||
d["__module__"] = module_name;
|
||||
|
||||
object result = (object(metatype))(
|
||||
module_name + name, make_tuple(base), d);
|
||||
object result = (object(metatype))(name, make_tuple(base), d);
|
||||
|
||||
scope().attr(name) = result;
|
||||
|
||||
|
||||
@@ -507,7 +507,8 @@ void function::add_to_namespace(
|
||||
{
|
||||
if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
|
||||
&& mutable_attribute.attr("__doc__")) {
|
||||
mutable_attribute.attr("__doc__") += "\n";
|
||||
mutable_attribute.attr("__doc__") += (
|
||||
mutable_attribute.attr("__doc__")[-1] != "\n" ? "\n\n" : "\n");
|
||||
}
|
||||
else {
|
||||
mutable_attribute.attr("__doc__") = "";
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/dict.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -19,6 +20,22 @@ namespace {
|
||||
object instance_class(instance_obj.attr("__class__"));
|
||||
result.append(instance_class);
|
||||
object none;
|
||||
if (!getattr(instance_obj, "__safe_for_unpickling__", none))
|
||||
{
|
||||
str type_name(getattr(instance_class, "__name__"));
|
||||
str module_name(getattr(instance_class, "__module__", object("")));
|
||||
if (module_name)
|
||||
module_name += ".";
|
||||
|
||||
PyErr_SetObject(
|
||||
PyExc_RuntimeError,
|
||||
( "Pickling of \"%s\" instances is not enabled"
|
||||
" (http://www.boost.org/libs/python/doc/v2/pickle.html)"
|
||||
% (module_name+type_name)).ptr()
|
||||
);
|
||||
|
||||
throw_error_already_set();
|
||||
}
|
||||
object getinitargs = getattr(instance_obj, "__getinitargs__", none);
|
||||
tuple initargs;
|
||||
if (getinitargs.ptr() != none.ptr()) {
|
||||
|
||||
@@ -27,33 +27,25 @@ rule py-compile-fail ( sources * )
|
||||
}
|
||||
|
||||
|
||||
|
||||
#template py-unit-test
|
||||
# :
|
||||
# : $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
|
||||
# [ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ] <define>BOOST_PYTHON_STATIC_LIB
|
||||
# ;
|
||||
|
||||
|
||||
test-suite python
|
||||
:
|
||||
|
||||
[
|
||||
run exec.cpp ../build//boost_python/<link>static /python//python
|
||||
: # program args
|
||||
: exec.py # input files
|
||||
: # requirements
|
||||
: # target-name
|
||||
]
|
||||
|
||||
[
|
||||
run exec.cpp ../build//boost_python/<link>shared /python//python
|
||||
: # program args
|
||||
: exec.py
|
||||
: # requirements
|
||||
: exec-dynamic # target-name
|
||||
<define>BOOST_PYTHON_STATIC_MODULE
|
||||
]
|
||||
|
||||
# [
|
||||
# run import_.cpp ../build//boost_python /python//python
|
||||
# : # program args
|
||||
# : import_.py # input files
|
||||
# : # requirements
|
||||
# : # target-name
|
||||
# ]
|
||||
|
||||
[
|
||||
bpl-test crossmod_exception
|
||||
: crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp
|
||||
@@ -76,7 +68,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test minimal ]
|
||||
[ bpl-test args ]
|
||||
[ bpl-test raw_ctor ]
|
||||
[ bpl-test numpy : numpy.py printer.py numeric_tests.py numarray_tests.py numpy.cpp ]
|
||||
[ bpl-test numpy : printer.py numeric_tests.py numarray_tests.py numpy.py numpy.cpp ]
|
||||
[ bpl-test enum ]
|
||||
[ bpl-test exception_translator ]
|
||||
[ bpl-test pearu1 : test_cltree.py cltree.cpp ]
|
||||
@@ -85,11 +77,12 @@ bpl-test crossmod_exception
|
||||
[ bpl-test keywords : keywords.cpp keywords_test.py ]
|
||||
|
||||
|
||||
[ python-extension builtin_converters_ext : test_builtin_converters.cpp /boost/python//boost_python ]
|
||||
[ bpl-test builtin_converters : test_builtin_converters.py builtin_converters_ext ]
|
||||
[ python-extension builtin_converters.ext : test_builtin_converters.cpp /boost/python//boost_python ]
|
||||
[ bpl-test builtin_converters : test_builtin_converters.py builtin_converters.ext ]
|
||||
|
||||
[ bpl-test test_pointer_adoption ]
|
||||
[ bpl-test operators ]
|
||||
[ bpl-test operators_wrapper ]
|
||||
[ bpl-test callbacks ]
|
||||
[ bpl-test defaults ]
|
||||
|
||||
@@ -152,13 +145,14 @@ bpl-test crossmod_opaque
|
||||
# Whenever the cause for the failure of the polymorphism test is found
|
||||
# and fixed, this should be retested.
|
||||
<toolset>hp_cxx:<build>no ]
|
||||
|
||||
|
||||
[ python-extension map_indexing_suite_ext
|
||||
: map_indexing_suite.cpp int_map_indexing_suite.cpp
|
||||
/boost/python//boost_python ]
|
||||
[ bpl-test
|
||||
map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ]
|
||||
|
||||
[ py-run import_.cpp : import_.py ]
|
||||
|
||||
# if $(TEST_BIENSTMAN_NON_BUGS)
|
||||
# {
|
||||
# bpl-test bienstman4 ;
|
||||
|
||||
20
test/args.py
20
test/args.py
@@ -84,22 +84,24 @@
|
||||
(2, 4.25, 'wow')
|
||||
>>> q.f1()
|
||||
(1, 4.25, 'wow')
|
||||
>>> q.f2.__doc__.splitlines()[-4]
|
||||
"f2's docstring"
|
||||
|
||||
>>> X.f.__doc__.splitlines()[:2]
|
||||
["This is X.f's docstring", 'C++ signature:']
|
||||
>>> X.f.__doc__.splitlines()[:3]
|
||||
["This is X.f's docstring", '', 'C++ signature:']
|
||||
|
||||
>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5)
|
||||
>>> for f in xfuncs:
|
||||
... print f(q,1).value(),
|
||||
... print f(q, n = 1).value(),
|
||||
... print f(q, n = 0).value(),
|
||||
... print f.__doc__.splitlines()[:2]
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
... print f.__doc__.splitlines()[:3]
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
1 1 0 ['docstring', '', 'C++ signature:']
|
||||
|
||||
>>> x = X(a1 = 44, a0 = 22)
|
||||
>>> x.inner0(0).value()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/python/reference_existing_object.hpp>
|
||||
#include <boost/python/call.hpp>
|
||||
#include <boost/python/object.hpp>
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
... doc = obj.__doc__.splitlines()
|
||||
... return "\\n".join(["|"+doc[i] for i in args])
|
||||
|
||||
>>> print selected_doc(X.__init__, 0, 2, 4, 6, 8, 9, 10, 12)
|
||||
>>> print selected_doc(X.__init__, 0, 3, 6, 9, 11, 12, 14, 17)
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
@@ -123,11 +123,11 @@
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(Y.__init__, 0, 1)
|
||||
>>> print selected_doc(Y.__init__, 0, 2)
|
||||
|doc of Y init
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(X.bar2, 0, 2, 4, 6, 8, 9, 10)
|
||||
>>> print selected_doc(X.bar2, 0, 3, 6, 9, 11, 12, 14)
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
... doc = obj.__doc__.splitlines()
|
||||
... return "\\n".join(["|"+doc[i] for i in args])
|
||||
|
||||
>>> print selected_doc(X.__init__, 0, 1, 2)
|
||||
>>> print selected_doc(X.__init__, 0, 1, 3)
|
||||
|this is the __init__ function
|
||||
|its documentation has two lines.
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(X.value, 0, 1, 3, 4, 5)
|
||||
>>> print selected_doc(X.value, 0, 2, 4, 5, 7)
|
||||
|gets the value of the object
|
||||
|C++ signature:
|
||||
|
|
||||
|also gets the value of the object
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(create, 0, 1)
|
||||
>>> print selected_doc(create, 0, 2)
|
||||
|creates a new X object
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(fact, 0, 1)
|
||||
>>> print selected_doc(fact, 0, 2)
|
||||
|compute the factorial
|
||||
|C++ signature:
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
>>> print selected_doc(fact_usr_off_1, 0)
|
||||
|C++ signature:
|
||||
>>> len(fact_usr_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_1, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_usr_on_1, 0, 2)
|
||||
|usr on 1
|
||||
|C++ signature:
|
||||
>>> len(fact_usr_off_2.__doc__.splitlines())
|
||||
@@ -42,8 +42,8 @@
|
||||
>>> print selected_doc(fact_usr_off_2, 0)
|
||||
|C++ signature:
|
||||
>>> len(fact_usr_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_2, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_usr_on_2, 0, 2)
|
||||
|usr on 2
|
||||
|C++ signature:
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
>>> print selected_doc(fact_sig_off_1, 0)
|
||||
|sig off 1
|
||||
>>> len(fact_sig_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_sig_on_1, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_sig_on_1, 0, 2)
|
||||
|sig on 1
|
||||
|C++ signature:
|
||||
>>> len(fact_sig_off_2.__doc__.splitlines())
|
||||
@@ -61,16 +61,16 @@
|
||||
>>> print selected_doc(fact_sig_off_2, 0)
|
||||
|sig off 2
|
||||
>>> len(fact_sig_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_sig_on_2, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_sig_on_2, 0, 2)
|
||||
|sig on 2
|
||||
|C++ signature:
|
||||
|
||||
>>> print fact_usr_off_sig_off_1.__doc__
|
||||
None
|
||||
>>> len(fact_usr_on_sig_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_sig_on_1, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_usr_on_sig_on_1, 0, 2)
|
||||
|usr on sig on 1
|
||||
|C++ signature:
|
||||
>>> len(fact_usr_on_sig_off_1.__doc__.splitlines())
|
||||
@@ -78,8 +78,8 @@ None
|
||||
>>> print selected_doc(fact_usr_on_sig_off_1, 0)
|
||||
|usr on sig off 1
|
||||
>>> len(fact_usr_on_sig_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_sig_on_2, 0, 1)
|
||||
4
|
||||
>>> print selected_doc(fact_usr_on_sig_on_2, 0, 2)
|
||||
|usr on sig on 2
|
||||
|C++ signature:
|
||||
>>> print fact_usr_off_sig_off_2.__doc__
|
||||
|
||||
17
test/enum.py
17
test/enum.py
@@ -48,14 +48,27 @@ enum_ext.color.red
|
||||
enum_ext.color.green
|
||||
'''
|
||||
|
||||
# pickling of enums only works with Python 2.3 or higher
|
||||
exercise_pickling = '''
|
||||
>>> import pickle
|
||||
>>> p = pickle.dumps(color.green, pickle.HIGHEST_PROTOCOL)
|
||||
>>> l = pickle.loads(p)
|
||||
>>> identity(l)
|
||||
enum_ext.color.green
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
import pickle
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
self = sys.modules.get(__name__)
|
||||
if (hasattr(pickle, "HIGHEST_PROTOCOL")):
|
||||
self.__doc__ += exercise_pickling
|
||||
return doctest.testmod(self)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
|
||||
@@ -49,6 +49,13 @@ BOOST_PYTHON_MODULE(embedded_hello)
|
||||
}
|
||||
|
||||
|
||||
void eval_test()
|
||||
{
|
||||
python::object result = python::eval("'abcdefg'.upper()");
|
||||
std::string value = python::extract<std::string>(result) BOOST_EXTRACT_WORKAROUND;
|
||||
BOOST_TEST(value == "ABCDEFG");
|
||||
}
|
||||
|
||||
void exec_test()
|
||||
{
|
||||
// Register the module with the interpreter
|
||||
@@ -108,7 +115,8 @@ int main(int argc, char **argv)
|
||||
// Initialize the interpreter
|
||||
Py_Initialize();
|
||||
|
||||
if (python::handle_exception(exec_test) ||
|
||||
if (python::handle_exception(eval_test) ||
|
||||
python::handle_exception(exec_test) ||
|
||||
python::handle_exception(boost::bind(exec_file_test, script)))
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
|
||||
@@ -4,28 +4,15 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace bpl = boost::python;
|
||||
|
||||
void import_test( char** argv )
|
||||
void import_test()
|
||||
{
|
||||
// Retrieve the main module
|
||||
bpl::object main = bpl::import("__main__");
|
||||
|
||||
// Retrieve the main module's namespace
|
||||
bpl::object global(main.attr("__dict__"));
|
||||
|
||||
// Inject search path for import_ module
|
||||
std::ostringstream script;
|
||||
script << "import sys, os\n"
|
||||
<< "path = os.path.dirname('" << argv[1] << "')\n"
|
||||
<< "sys.path.insert(0, path)\n";
|
||||
bpl::exec(bpl::str(script.str()), global, global);
|
||||
|
||||
// Retrieve the main module
|
||||
bpl::object import_ = bpl::import("import_");
|
||||
int value = bpl::extract<int>(import_.attr("value")) BOOST_EXTRACT_WORKAROUND;
|
||||
@@ -40,7 +27,19 @@ int main(int argc, char **argv)
|
||||
// Initialize the interpreter
|
||||
Py_Initialize();
|
||||
|
||||
if (bpl::handle_exception(boost::bind(import_test, argv)))
|
||||
// Retrieve the main module
|
||||
bpl::object main = bpl::import("__main__");
|
||||
|
||||
// Retrieve the main module's namespace
|
||||
bpl::object global(main.attr("__dict__"));
|
||||
|
||||
// Inject search path for import_ module
|
||||
std::ostringstream script;
|
||||
script << "import sys, os.path\n"
|
||||
<< "path = os.path.dirname('" << argv[1] << "')\n"
|
||||
<< "sys.path.insert(0, path)\n";
|
||||
bpl::object result = bpl::exec(bpl::str(script.str()), global, global);
|
||||
if (bpl::handle_exception(import_test))
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
|
||||
@@ -103,6 +103,7 @@ BOOST_PYTHON_MODULE(keywords)
|
||||
, init<optional<int, double, const std::string &> >()
|
||||
)
|
||||
.def("set", &Bar::set, bar_set())
|
||||
.def("set2", &Bar::set, bar_set("set2's docstring"))
|
||||
.def("seta", &Bar::seta, arg("a"))
|
||||
|
||||
.def("a", &Bar::geta)
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
>>> f.set(1,1.0,"1")
|
||||
>>> f.a(), f.b(), f.n()
|
||||
(1, 1.0, '1')
|
||||
>>> f.set2.__doc__.splitlines()[-4]
|
||||
"set2's docstring"
|
||||
'''
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/make_function.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
#include <boost/assert.hpp>
|
||||
#include "test_class.hpp"
|
||||
|
||||
@@ -143,3 +144,4 @@ BOOST_PYTHON_MODULE(list_ext)
|
||||
;
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
|
||||
@@ -26,6 +26,62 @@ std::string x_value(X const& x)
|
||||
return "gotya " + x.s;
|
||||
}
|
||||
|
||||
struct A
|
||||
{
|
||||
int value;
|
||||
A() : value(0){};
|
||||
A(int v) : value(v) {};
|
||||
};
|
||||
|
||||
bool operator==(const A& v1, const A& v2)
|
||||
{
|
||||
return (v1.value == v2.value);
|
||||
}
|
||||
|
||||
struct B
|
||||
{
|
||||
A a;
|
||||
};
|
||||
|
||||
// Converter from A to python int
|
||||
struct AToPython
|
||||
{
|
||||
static PyObject* convert(const A& s)
|
||||
{
|
||||
return boost::python::incref(boost::python::object((int)s.value).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
// Conversion from python int to A
|
||||
struct AFromPython
|
||||
{
|
||||
AFromPython()
|
||||
{
|
||||
boost::python::converter::registry::push_back(
|
||||
&convertible,
|
||||
&construct,
|
||||
boost::python::type_id< A >());
|
||||
}
|
||||
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
if (!PyInt_Check(obj_ptr)) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(
|
||||
PyObject* obj_ptr,
|
||||
boost::python::converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
void* storage = (
|
||||
(boost::python::converter::rvalue_from_python_storage< A >*)
|
||||
data)-> storage.bytes;
|
||||
|
||||
new (storage) A((int)PyInt_AsLong(obj_ptr));
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(map_indexing_suite_ext)
|
||||
{
|
||||
class_<X>("X")
|
||||
@@ -58,6 +114,18 @@ BOOST_PYTHON_MODULE(map_indexing_suite_ext)
|
||||
class_<std::map<std::string, boost::shared_ptr<X> > >("TestMap")
|
||||
.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<X> >, true>())
|
||||
;
|
||||
|
||||
to_python_converter< A , AToPython >();
|
||||
AFromPython();
|
||||
|
||||
class_< std::map<int, A> >("AMap")
|
||||
.def(map_indexing_suite<std::map<int, A>, true >())
|
||||
;
|
||||
|
||||
class_< B >("B")
|
||||
.add_property("a", make_getter(&B::a, return_value_policy<return_by_value>()),
|
||||
make_setter(&B::a, return_value_policy<return_by_value>()))
|
||||
;
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
>>> assert "map_indexing_suite_IntMap_entry" in dir()
|
||||
>>> assert "map_indexing_suite_TestMap_entry" in dir()
|
||||
>>> assert "map_indexing_suite_XMap_entry" in dir()
|
||||
>>> assert "map_indexing_suite_AMap_entry" in dir()
|
||||
>>> x = X('hi')
|
||||
>>> x
|
||||
hi
|
||||
@@ -201,6 +202,18 @@ kiwi
|
||||
... dom = el.data()
|
||||
joel kimpo
|
||||
|
||||
#####################################################################
|
||||
# Test custom converter...
|
||||
#####################################################################
|
||||
|
||||
>>> am = AMap()
|
||||
>>> am[3] = 4
|
||||
>>> am[3]
|
||||
4
|
||||
>>> for i in am:
|
||||
... i.data()
|
||||
4
|
||||
|
||||
#####################################################################
|
||||
# END....
|
||||
#####################################################################
|
||||
|
||||
@@ -32,7 +32,7 @@ extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)
|
||||
#include <boost/python/str.hpp>
|
||||
struct test_failure : std::exception
|
||||
{
|
||||
test_failure(char const* expr, char const* function, char const* file, unsigned line)
|
||||
test_failure(char const* expr, char const* /*function*/, char const* file, unsigned line)
|
||||
: msg(file + boost::python::str(":%s:") % line + ": Boost.Python assertion failure: " + expr)
|
||||
{}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
// To support test of "pickling not enabled" error message.
|
||||
struct noop {};
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(pickle1_ext)
|
||||
@@ -54,4 +56,7 @@ BOOST_PYTHON_MODULE(pickle1_ext)
|
||||
.def("greet", &world::greet)
|
||||
.def_pickle(world_pickle_suite())
|
||||
;
|
||||
|
||||
// To support test of "pickling not enabled" error message.
|
||||
class_<noop>("noop");
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ r'''>>> import pickle1_ext
|
||||
Hello from California!
|
||||
>>> print wl.greet()
|
||||
Hello from California!
|
||||
|
||||
>>> noop = pickle1_ext.noop()
|
||||
>>> try: pickle.dumps(noop)
|
||||
... except RuntimeError, e: print str(e)[:55]
|
||||
Pickling of "pickle1_ext.noop" instances is not enabled
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/python/call_method.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -57,7 +57,7 @@ char const* rewrap_value_mutable_cstring(char* x) { return x; }
|
||||
|
||||
object identity_(object x) { return x; }
|
||||
|
||||
BOOST_PYTHON_MODULE(builtin_converters_ext)
|
||||
BOOST_PYTHON_MODULE(builtin_converters)
|
||||
{
|
||||
def("get_type", get_type);
|
||||
def("return_null_handle", return_null_handle);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
r"""
|
||||
>>> from builtin_converters_ext import *
|
||||
>>> from builtin_converters import *
|
||||
|
||||
# Synthesize idendity functions in case long long not supported
|
||||
>>> if not 'rewrap_value_long_long' in dir():
|
||||
@@ -250,9 +250,9 @@ Check that classic classes also work
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
import builtin_converters_ext
|
||||
import builtin_converters
|
||||
|
||||
if 'rewrap_value_long_long' in dir(builtin_converters_ext):
|
||||
if 'rewrap_value_long_long' in dir(builtin_converters):
|
||||
print 'LONG_LONG supported, testing...'
|
||||
else:
|
||||
print 'LONG_LONG not supported, skipping those tests...'
|
||||
|
||||
@@ -53,5 +53,10 @@ BOOST_PYTHON_MODULE(vector_indexing_suite_ext)
|
||||
class_<std::vector<bool> >("BoolVec")
|
||||
.def(vector_indexing_suite<std::vector<bool> >())
|
||||
;
|
||||
|
||||
// vector of strings
|
||||
class_<std::vector<std::string> >("StringVec")
|
||||
.def(vector_indexing_suite<std::vector<std::string> >())
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -321,6 +321,14 @@ e
|
||||
>>> print_xvec(v)
|
||||
[ a b c d e f g h i j ]
|
||||
|
||||
#####################################################################
|
||||
# vector of strings
|
||||
#####################################################################
|
||||
>>> sv = StringVec()
|
||||
>>> sv.append('a')
|
||||
>>> print sv[0]
|
||||
a
|
||||
|
||||
#####################################################################
|
||||
# END....
|
||||
#####################################################################
|
||||
|
||||
Reference in New Issue
Block a user