2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

Compare commits

...

82 Commits

Author SHA1 Message Date
Dave Abrahams
eceab34284 *** empty log message ***
[SVN r32838]
2006-02-11 23:01:32 +00:00
Dave Abrahams
5f505d6ba8 void pointer conversion support, from Niall Douglas, then heavily
edited by DWA.


[SVN r32836]
2006-02-11 22:29:33 +00:00
nobody
dd30e8c45c This commit was manufactured by cvs2svn to create branch
'python-voidptr'.

[SVN r32815]
2006-02-10 17:26:07 +00:00
Dave Abrahams
c39836ddc8 Tests for bool conversions
[SVN r32814]
2006-02-10 17:26:06 +00:00
Dave Abrahams
fb35a82bf1 Tests for bool members
[SVN r32813]
2006-02-10 17:25:25 +00:00
Vladimir Prus
44c5c18f45 Update Jamfile.v2
[SVN r32761]
2006-02-09 09:50:56 +00:00
Vladimir Prus
e0cceeb88c Update.
[SVN r32722]
2006-02-08 08:37:05 +00:00
Vladimir Prus
4a5f6f2e24 Update Jamfile.v2
[SVN r32702]
2006-02-07 11:49:00 +00:00
Dave Abrahams
8b1748fea0 add tuple conversion
[SVN r32473]
2006-01-31 03:26:46 +00:00
Ralf W. Grosse-Kunstleve
82919f0d5c another attempt to fix Code Warrior 9.4 link problem
[SVN r32404]
2006-01-24 17:55:56 +00:00
Ralf W. Grosse-Kunstleve
1f6ded7b4e Boost.Python docstring_options.hpp news
[SVN r32390]
2006-01-24 00:41:25 +00:00
Ralf W. Grosse-Kunstleve
a0d2873156 attempt to fix Code Warrior 9.4 link problem
[SVN r32380]
2006-01-23 19:01:17 +00:00
Ralf W. Grosse-Kunstleve
0519d54229 avoid g++ -Wall -W "unused parameter" warnings
[SVN r32373]
2006-01-22 19:29:32 +00:00
Ralf W. Grosse-Kunstleve
c181874335 initialize all slots of PyTypeObject to avoid g++ -Wall -W warnings
[SVN r32372]
2006-01-22 19:26:50 +00:00
Ralf W. Grosse-Kunstleve
203a42c35f avoid g++ -Wall -W "unused parameter" warnings
[SVN r32371]
2006-01-22 19:21:22 +00:00
Ralf W. Grosse-Kunstleve
8eba0eb25b initialize all slots of PyTypeObject to avoid g++ -Wall -W warnings
[SVN r32370]
2006-01-22 19:21:08 +00:00
Dave Abrahams
152e76220a GCC warning suppression from Jody Hagins
[SVN r32363]
2006-01-20 15:55:55 +00:00
Ralf W. Grosse-Kunstleve
8897cc9ce6 selected_doc() helper function modified to increase readability
[SVN r32339]
2006-01-16 20:54:53 +00:00
Ralf W. Grosse-Kunstleve
335cd02c2d new documentation for docstring_options.hpp
[SVN r32338]
2006-01-16 20:37:23 +00:00
Ralf W. Grosse-Kunstleve
758d92b33e seq.attr("__len__")() replaced by len(seq); obsolete len() example removed
[SVN r32337]
2006-01-16 20:36:42 +00:00
Ralf W. Grosse-Kunstleve
28eef45d28 enum_print() removed; it was not reachable anyway since enum inherits
from Python's built-in int type. However, the appearance of FILE*
raised questions about using extensions compiled with Visual C++ 8
with a Python compiled with Visual C++ 7.1.


[SVN r32301]
2006-01-12 23:25:23 +00:00
Ralf W. Grosse-Kunstleve
d8790a34d3 boost::python::len() moved to object.hpp
[SVN r32299]
2006-01-12 21:33:19 +00:00
Ralf W. Grosse-Kunstleve
3b058185c6 new docstring_options to support customization of __doc__ attributes of Boost.Python functions
[SVN r32298]
2006-01-12 19:28:53 +00:00
Ralf W. Grosse-Kunstleve
2261e7eedc new docstring_options to support customization of __doc__ attributes of Boost.Python functions
[SVN r32297]
2006-01-12 19:15:38 +00:00
Ralf W. Grosse-Kunstleve
19a196493f Runtime detection of broken cxxabi::__cxa_demangle versions; based on code contributed by Ult Mundane
[SVN r32296]
2006-01-12 19:12:27 +00:00
Ralf W. Grosse-Kunstleve
d10b5e8d1a Python 2.2 compatibility
[SVN r32295]
2006-01-12 17:49:48 +00:00
Ralf W. Grosse-Kunstleve
1cacefc226 automatic addition of C++ signatures to doc strings
[SVN r32290]
2006-01-12 00:32:29 +00:00
Ralf W. Grosse-Kunstleve
efcd2833f1 Visual C++ 6 compatibility
[SVN r32288]
2006-01-11 19:58:55 +00:00
Ralf W. Grosse-Kunstleve
2f9323d9e9 resolve gcc warnings (based on patches by Scott Howlett)
[SVN r32284]
2006-01-11 03:31:48 +00:00
Eric Niebler
8b2f4b4ce0 make test work on vc6
[SVN r31960]
2005-12-08 22:15:31 +00:00
Douglas Gregor
ab046dc634 Merged from Version_1_33_1
[SVN r31953]
2005-12-08 04:11:36 +00:00
Dave Abrahams
ef3f9b15f0 vc-8 workaround
[SVN r31943]
2005-12-07 05:00:02 +00:00
Dave Abrahams
68463e2fd2 Fixed missing semicolon
[SVN r31852]
2005-12-01 13:06:57 +00:00
Dave Abrahams
f75eca94e0 Fix typo
[SVN r31831]
2005-11-30 11:57:33 +00:00
Dave Abrahams
a23030b83e use symbol visibility for GCC 4.x
[SVN r31828]
2005-11-29 22:26:48 +00:00
Dave Abrahams
321cf2502a use symbol visibility for GCC 4.x
[SVN r31827]
2005-11-29 22:26:05 +00:00
Dave Abrahams
4996f912b4 Workaround for GCC bug described in http://lists.debian.org/debian-gcc/2003/09/msg00055.html
Thanks to Graham Bennett.


[SVN r31809]
2005-11-28 21:16:12 +00:00
Joel de Guzman
09e24cb17d map bug fix when data type is a shared_ptr and NoProxy is true
[SVN r31787]
2005-11-26 16:23:21 +00:00
Joel de Guzman
ac32d13e10 added more tests
[SVN r31786]
2005-11-26 15:13:20 +00:00
Joel de Guzman
b0496d1207 update: map indexing suite
[SVN r31723]
2005-11-21 15:25:47 +00:00
Joel de Guzman
a076239fc8 std::string and std::complex as no-proxy types.
[SVN r31717]
2005-11-21 04:54:23 +00:00
Dave Abrahams
7cf0f9090f Restore map_indexing_suite test that was mistakenly commented out.
[SVN r31621]
2005-11-10 21:58:20 +00:00
Dave Abrahams
479f068673 Attempt Bronek's change to suppress VC++8.0 complaints about redefined
_DEBUG.


[SVN r31557]
2005-11-04 21:38:29 +00:00
Eric Niebler
9b326f15fa qualify friend declaration to make EDG happy
[SVN r31538]
2005-11-02 22:43:05 +00:00
Ralf W. Grosse-Kunstleve
f094a5b9eb boost/python header must be included first due to a Python requirement
[SVN r31535]
2005-11-01 22:12:53 +00:00
Stefan Seefeld
4367850e5d Add examples.
[SVN r31530]
2005-11-01 15:18:02 +00:00
Dave Abrahams
f44a4d6468 Clarified HeldType
[SVN r31528]
2005-11-01 15:08:30 +00:00
Eric Niebler
5206dd55d2 s/Python sequences/Python iterables/ and other assorted feedback from Dave
[SVN r31517]
2005-10-31 19:46:41 +00:00
Dave Abrahams
988bf849a1 Account for Intel 9.0 picking up vc7.1 bug compatibility.
[SVN r31515]
2005-10-31 19:24:48 +00:00
Eric Niebler
6fee43fc6f tests and docs for stl_input_iterator
[SVN r31514]
2005-10-31 18:50:18 +00:00
Eric Niebler
6ec4387ea1 add stl_input_iterator for wrapping a Python iterator in a STL input iterator
[SVN r31513]
2005-10-31 18:49:54 +00:00
Dave Abrahams
e2f59ef548 More restrictions on the need for libpython.a
[SVN r31494]
2005-10-27 12:21:55 +00:00
Dave Abrahams
92a6fafd20 Note that the libpython.a creation instructions are not needed for Python 2.4.1+
[SVN r31466]
2005-10-25 19:08:24 +00:00
Dave Abrahams
4721f5f9af Fix CYGWIN_PYTHON_DEBUG_ROOT to be consistent with docs
Set *nix PYTHON_ROOT to /usr, to be consistent with real installations.
Use *nix rather than Unix everywhere for generality


[SVN r31463]
2005-10-25 15:47:27 +00:00
Dave Abrahams
3864838da2 Fixed for vc6
[SVN r31398]
2005-10-19 22:02:51 +00:00
Dave Abrahams
8e77df69d5 Update
[SVN r31396]
2005-10-19 18:28:02 +00:00
Dave Abrahams
12770b03e8 Add the ability to easily use new-style polymorphism wrappers with
smart pointer held_type.


[SVN r31392]
2005-10-19 18:17:13 +00:00
Dave Abrahams
c8a692b4b4 Bug fix
[SVN r31385]
2005-10-19 13:17:27 +00:00
Dave Abrahams
2571ebb0c2 Added Stefan's new files.
[SVN r31371]
2005-10-18 12:09:36 +00:00
Dave Abrahams
283dbfb593 Updated news
[SVN r31329]
2005-10-14 19:30:01 +00:00
Dave Abrahams
83f227034f Updated news
[SVN r31328]
2005-10-14 19:25:41 +00:00
Dave Abrahams
c5f514a4e6 Build with Python 2.4 by default; also deduce the default PYTHON_ROOT properly on Windows.
[SVN r31325]
2005-10-14 16:19:14 +00:00
Dave Abrahams
9fb15f631e Make it work when Python is compiled with Unicode disabled.
[SVN r31322]
2005-10-14 15:54:12 +00:00
Dave Abrahams
3d8f4c90ba Make it work when Python is compiled with Unicode disabled.
[SVN r31321]
2005-10-14 15:35:06 +00:00
Dave Abrahams
5597dcb321 Disable ADL from addressof uses :(
[SVN r31319]
2005-10-14 15:05:17 +00:00
Joel de Guzman
ab2912e3c2 minor fix
[SVN r31308]
2005-10-13 12:02:25 +00:00
Joel de Guzman
b705931ff0 tweak: wrong c++ code written in python
[SVN r31307]
2005-10-13 11:58:53 +00:00
Eric Niebler
2974286209 fix bugs in example code
[SVN r31305]
2005-10-12 20:17:28 +00:00
Dave Abrahams
1cec514b39 Martin Wille pointed out some missing header dependencies; fixed.
Also moved boost/python/detail/is_xxx.hpp functionality into
boost/detail/is_xxx.hpp to decouple library dependencies between
python and parameter.


[SVN r31290]
2005-10-11 21:20:06 +00:00
Dave Abrahams
8ecd49cbf0 Use "addressof(x)" instead of "&x" to deal with classes that have a
private operator& !!


[SVN r31279]
2005-10-11 13:19:05 +00:00
Ralf W. Grosse-Kunstleve
67a7669ff4 work around Visual C++ 6 problem
[SVN r31075]
2005-09-22 06:20:25 +00:00
Stefan Seefeld
e80545a7d3 Use BOOST_ASSERT instead of std::runtime_error to indicate errors.
[SVN r30954]
2005-09-13 14:42:03 +00:00
Stefan Seefeld
6afe0d4732 Enhance and clean up tests.
[SVN r30907]
2005-09-11 14:50:37 +00:00
Ralf W. Grosse-Kunstleve
f8280b0e1a David Abrahams, Jul 2005: according to 8.5/9 the __GNUC__ workaround at line 69 of data_members.cpp should be made universal.
[SVN r30893]
2005-09-10 05:53:28 +00:00
John Maddock
aa20ce7d2c Large patch from Ulrich Eckhardt to fix support for EVC++ 4.
[SVN r30670]
2005-08-25 16:27:28 +00:00
Stefan Seefeld
6074a23242 Fix exec test.
[SVN r30669]
2005-08-25 15:03:19 +00:00
Dave Abrahams
9ceac3ff8f Fix bug in example thanks to Roman Yakovenko.
[SVN r30616]
2005-08-21 15:19:51 +00:00
Stefan Seefeld
126a3efb92 Add basic embedding support.
[SVN r30601]
2005-08-17 13:04:42 +00:00
Victor A. Wagner Jr.
9205f507b0 Added - #define _CRT_NOFORCE_MANIFEST if we also have to #undef _DEBUG
this isn't really an elegant solution, perhaps people trying to
          debug python (BOOST_DEBUG_PYTHON defined) will really have to
          use the debug version of the CRT with the latest .NET

          There is also a collision if the user happens to have
          #define _CRT_FORCE_MANIFEST which I didn't address


[SVN r30570]
2005-08-13 16:19:19 +00:00
Ralf W. Grosse-Kunstleve
bff975f08c bug fix: friend class def_visitor_access; -> friend class python::def_visitor_access; This fix enables us to remove an EDG specific workaround.
[SVN r30471]
2005-08-04 20:15:35 +00:00
Dave Abrahams
262bcee750 Fix broken links
[SVN r30401]
2005-08-03 12:25:30 +00:00
Dave Abrahams
a3f12b18b1 Fix broken links
[SVN r30398]
2005-08-03 11:39:39 +00:00
122 changed files with 5656 additions and 3084 deletions

View File

@@ -51,9 +51,12 @@ if [ check-python-config ]
converter/builtin_converters.cpp converter/builtin_converters.cpp
converter/arg_to_python_base.cpp converter/arg_to_python_base.cpp
object/iterator.cpp object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp object_protocol.cpp
object_operators.cpp object_operators.cpp
wrapper.cpp wrapper.cpp
exec.cpp
import.cpp
; ;
dll boost_python dll boost_python

View File

@@ -50,9 +50,12 @@ lib boost_python
converter/builtin_converters.cpp converter/builtin_converters.cpp
converter/arg_to_python_base.cpp converter/arg_to_python_base.cpp
object/iterator.cpp object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp object_protocol.cpp
object_operators.cpp object_operators.cpp
wrapper.cpp wrapper.cpp
import.cpp
exec.cpp
: <link>static:<define>BOOST_PYTHON_STATIC_LIB : <link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE <define>BOOST_PYTHON_SOURCE
<library>/python//python <library>/python//python

View File

@@ -179,6 +179,10 @@ SOURCE=..\..\src\slice.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\src\object\stl_iterator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\str.cpp SOURCE=..\..\src\str.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -193,6 +197,14 @@ SOURCE=..\..\src\converter\type_id.cpp
SOURCE=..\..\src\wrapper.cpp SOURCE=..\..\src\wrapper.cpp
# End Source File # End Source File
# Begin Source File
SOURCE=..\..\src\import.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\exec.cpp
# End Source File
# End Group # End Group
# Begin Group "Header Files" # Begin Group "Header Files"
@@ -594,6 +606,10 @@ SOURCE=..\..\..\..\boost\python\object\select_holder.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\boost\python\object\stl_iterator_core.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\..\boost\python\object\value_holder.hpp SOURCE=..\..\..\..\boost\python\object\value_holder.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -851,6 +867,10 @@ SOURCE=..\..\..\..\boost\python\slice_nil.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\boost\python\stl_iterator.hpp
# End Source File
# Begin Source File
SOURCE=..\..\..\..\boost\python\str.hpp SOURCE=..\..\..\..\boost\python\str.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -82,9 +82,12 @@
boost installation (if you have already built boost from the top level boost installation (if you have already built boost from the top level
this may have no effect, since the work is already done).</p> this may have no effect, since the work is already done).</p>
<h3><a name="configuration">Basic Configuration</a></h3> <h3><a name="configuration">Basic Configuration</a></h3> You may
You may need to configure the following variables to point Boost.Build at need to configure the following variables to point Boost.Build at
your Python installation: 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"> <table border="1" summary="build configuration variables">
<tr> <tr>
@@ -98,28 +101,29 @@
</tr> </tr>
<tr> <tr>
<td><code>PYTHON_ROOT</code></td>
<td>The root directory of your Python installation</td>
<td>Windows:&nbsp;<code>c:/tools/python</code>
Unix:&nbsp;<code>/usr/local</code></td>
<td>On Unix, this is the <code>--with-prefix=</code> directory used
to configure Python</td>
</tr>
<tr> <tr>
<td><code>PYTHON_VERSION</code></td> <td><code>PYTHON_VERSION</code></td>
<td>The The 2-part python Major.Minor version number</td> <td>The The 2-part python Major.Minor version number</td>
<td><code>2.2</code></td> <td><code>2.4</code></td>
<td>Be sure not to include a third number, e.g. <b>not</b> <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> "<code>2.2.1</code>", even if that's the version you have.</td>
</tr> </tr>
<td><code>PYTHON_ROOT</code></td>
<td>The root directory of your Python installation</td>
<td>Windows:&nbsp;<code>c:/Python</code><i>(10*Version)</i>, e.g. <code>c:/Python24</code>
<br>
*nix/Cygwin:&nbsp;<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> <tr>
<td><code>PYTHON_INCLUDES</code></td> <td><code>PYTHON_INCLUDES</code></td>
@@ -172,7 +176,7 @@
<tr> <tr>
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td> <td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
<td>unix-style path containing the <code>include/</code> directory <td>*nix-style path containing the <code>include/</code> directory
containing containing
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td> <code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
@@ -219,8 +223,10 @@
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC <h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
Users</a></h3> Users</a></h3>
<p>You will need to create a MinGW-compatible version of the Python <p>If you are using a version of Python prior to 2.4.1 with a
library; the one shipped with Python will only work 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 Microsoft-compatible linker. Follow the instructions in the
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks" "Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
chapter in <a href= chapter in <a href=
@@ -302,7 +308,7 @@ bjam -sTOOLS=<i><a href=
right places. right places.
</blockquote> </blockquote>
<p>The <code><a href="../example">libs/python/example</a></code> <p>The <code>libs/python/example</code>
subdirectory of your boost installation contains a small example which subdirectory of your boost installation contains a small example which
builds and tests two extensions. To build your own extensions copy the builds and tests two extensions. To build your own extensions copy the
example subproject and make the following two edits:</p> example subproject and make the following two edits:</p>
@@ -359,7 +365,7 @@ path-global BOOST_ROOT : ../../.. ;
<p>The first two variants of the <code>boost_python</code> library are <p>The first two variants of the <code>boost_python</code> library are
built by default, and are compatible with the default Python built by default, and are compatible with the default Python
distribution. The <code>debug-python</code> variant corresponds to a distribution. The <code>debug-python</code> variant corresponds to a
specially-built debugging version of Python. On Unix platforms, this specially-built debugging version of Python. On *nix platforms, this
python is built by adding <code>--with-pydebug</code> when configuring python is built by adding <code>--with-pydebug</code> when configuring
the Python build. On Windows, the debugging version of Python is the Python build. On Windows, the debugging version of Python is
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code> generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
@@ -396,8 +402,8 @@ path-global BOOST_ROOT : ../../.. ;
IDE</a></h2> IDE</a></h2>
<p>For the those of you who feel more comfortable in the IDE world, a <p>For the those of you who feel more comfortable in the IDE world, a
workspace and project file have been included in the <a href= workspace and project file have been included in the <code>
"../build/VisualStudio">libs/python/build/VisualStudio</a> subdirectory. libs/python/build/VisualStudio</code> subdirectory.
It builds release and debug versions of the Boost.Python libraries and It builds release and debug versions of the Boost.Python libraries and
places them and the same directory as Jamfile build does, though the places them and the same directory as Jamfile build does, though the
intermediate object files are placed in a different directory. The files intermediate object files are placed in a different directory. The files

View File

@@ -1,105 +1,184 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<meta name="generator" content= <meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org"> "HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="boost.css"> <link rel="stylesheet" type="text/css" href="boost.css">
<title>Boost.Python - News/Change Log</title> <title>Boost.Python - News/Change Log</title>
</head> </head>
<body link="#0000ff" vlink="#800080"> <body link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary= <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header"> "header">
<tr> <tr>
<td valign="top" width="300"> <td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt= <h3><a href="../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../boost.png" border="0"></a></h3> "C++ Boost" src="../../../boost.png" border="0"></a></h3>
</td> </td>
<td valign="top"> <td valign="top">
<h1 align="center"><a href="index.html">Boost.Python</a></h1> <h1 align="center"><a href="index.html">Boost.Python</a></h1>
<h2 align="center">News/Change Log</h2> <h2 align="center">News/Change Log</h2>
</td> </td>
</tr> </tr>
</table> </table>
<hr> <hr>
<dl class="page-index"> <dl class="page-index">
<dt>11 March 2005</dt> <dt>Current CVS</dt>
<dd> <dd>
<ul> <ul>
<li>Added a hack that will fool PyDoc into working with Boost.Python, thanks to Nick Rasmussen</li> <li>C++ signatures are now automatically appended to the
</ul> docstrings.
</dd>
<dt>19 November 2004 - 1.32 release</dt>
<dd> <li>New <a href="v2/docstring_options.html"
<ul> ><code>docstring_options.hpp</code></a> header to
<li>Updated to use the Boost Software License.</li> control the content of docstrings.
<li>A new, <a href="tutorial/doc/html/python/exposing.html#python.class_virtual_functions">better method of wrapping classes with virtual functions</a> has been implemented.</li> </ul>
<li>Support for upcoming GCC symbol export control features have been folded in, thanks to Niall Douglas.</li> </dd>
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i> of function parameter types part of the function type has been worked around.</li>
<li>Components used by other libraries have been moved out of <code>python/detail</code> and into <code> boost/detail</code> to improve dependency relationships.</li>
<li>Miscellaneous bug fixes and compiler workarounds.</li>
</ul>
</dd>
<dt>8 Sept 2004</dt>
<dd> <dt>19 October 2005 - 1.33.1 release</dt>
Support for Python's Bool type, thanks to <a
mailto="dholth-at-fastmail.fm">Daniel Holth</a>.
</dd>
<dt>11 Sept 2003</dt> <dd>
<ul>
<li><code>wrapper&lt;T&gt;</code> can now be used as expected with a
held type of <i>some-smart-pointer</i><code>&lt;T&gt;</code></li>
<dd> <li>The build now assumes Python 2.4 by default, rather than 2.2</li>
<ul>
<li>Changed the response to multiple to-python converters being
registered for the same type from a hard error into warning;
Boost.Python now reports the offending type in the message.</li>
<li>Added builtin <code>std::wstring</code> conversions</li> <li>Support Python that's built without Unicode support</li>
<li>Added <code>std::out_of_range</code> =&gt; Python <li>Support for wrapping classes with overloaded address-of
<code>IndexError</code> exception conversion, thanks to <a href= (<code>&amp;</code>) operators</li>
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li> </ul>
</ul> </dd>
</dd>
<dt>9 Sept 2003</dt> <dt>14 August 2005 - 1.33 release</dt>
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd> <dd>
<ul>
<li>Support for docstrings on nonstatic properties.</li>
<dt>constructors which take a range of characters, allowing strings <li>We now export the client-provided docstrings for
containing nul (<code>'\0'</code>) characters.</dt> <code>init&lt;optional&lt;&gt; &gt;</code> and
<i>XXX</i><code>_FUNCTION_OVERLOADS()</code> for only the last
overload.</li>
<dt>8 Sept 2003</dt> <li>Fixed some support for Embedded VC++ 4</li>
<dd>Added the ability to create methods from function objects (with an <li>Better support for rvalue from-python conversions of shared_ptr:
<code>operator()</code>); see the <a href= always return a pointer that holds the owning python object *unless*
"v2/make_function.html#make_function-spec">make_function</a> docs for the python object contains a NULL shared_ptr holder of the right
more info.</dd> type.</li>
<dt>10 August 2003</dt> <li>Support for exposing <code>vector&lt;T*&gt;</code> with the
indexing suite.</li>
<dd>Added the new <code>properties</code> unit tests contributed by <a <li>Support for GCC-3.3 on MacOS.</li>
href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and documented
<code>add_static_property</code> at his urging.</dd>
<dt>1 August 2003</dt> <li>updated visual studio project build file to include two new files
(slice.cpp and wrapper.cpp)</li>
<dd> <li>Added search feature to the index page.</li>
Added the new <code>arg</code> class contributed by <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the <li>Numerous fixes to the tutorial</li>
ability to wrap functions that can be called with ommitted arguments
in the middle: <li>Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG
<pre> 2.45</li>
</ul>
</dd>
<dt>11 March 2005</dt>
<dd>
<ul>
<li>Added a hack that will fool PyDoc into working with Boost.Python,
thanks to Nick Rasmussen</li>
</ul>
</dd>
<dt>19 November 2004 - 1.32 release</dt>
<dd>
<ul>
<li>Updated to use the Boost Software License.</li>
<li>A new, <a href=
"tutorial/doc/html/python/exposing.html#python.class_virtual_functions">
better method of wrapping classes with virtual functions</a> has been
implemented.</li>
<li>Support for upcoming GCC symbol export control features have been
folded in, thanks to Niall Douglas.</li>
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i>
of function parameter types part of the function type has been worked
around.</li>
<li>Components used by other libraries have been moved out of
<code>python/detail</code> and into <code>boost/detail</code> to
improve dependency relationships.</li>
<li>Miscellaneous bug fixes and compiler workarounds.</li>
</ul>
</dd>
<dt>8 Sept 2004</dt>
<dd>Support for Python's Bool type, thanks to <a href=
"mailto:dholth-at-fastmail.fm">Daniel Holth</a>.</dd>
<dt>11 Sept 2003</dt>
<dd>
<ul>
<li>Changed the response to multiple to-python converters being
registered for the same type from a hard error into warning;
Boost.Python now reports the offending type in the message.</li>
<li>Added builtin <code>std::wstring</code> conversions</li>
<li>Added <code>std::out_of_range</code> =&gt; Python
<code>IndexError</code> exception conversion, thanks to <a href=
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
</ul>
</dd>
<dt>9 Sept 2003</dt>
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
<dt>constructors which take a range of characters, allowing strings
containing nul (<code>'\0'</code>) characters.</dt>
<dt>8 Sept 2003</dt>
<dd>Added the ability to create methods from function objects (with an
<code>operator()</code>); see the <a href=
"v2/make_function.html#make_function-spec">make_function</a> docs for
more info.</dd>
<dt>10 August 2003</dt>
<dd>Added the new <code>properties</code> unit tests contributed by
<a href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and
documented <code>add_static_property</code> at his urging.</dd>
<dt>1 August 2003</dt>
<dd>
Added the new <code>arg</code> class contributed by <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
ability to wrap functions that can be called with ommitted arguments in
the middle:
<pre>
void f(int x = 0, double y = 3.14, std::string z = std::string("foo")); void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
BOOST_PYTHON_MODULE(test) BOOST_PYTHON_MODULE(test)
@@ -108,111 +187,104 @@ BOOST_PYTHON_MODULE(test)
, (arg("x", 0), arg("y", 3.14), arg("z", "foo"))); , (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
} }
</pre> </pre>And in Python:
And in Python: <pre>
<pre>
&gt;&gt;&gt; import test &gt;&gt;&gt; import test
&gt;&gt;&gt; f(0, z = "bar") &gt;&gt;&gt; f(0, z = "bar")
&gt;&gt;&gt; f(z = "bar", y = 0.0) &gt;&gt;&gt; f(z = "bar", y = 0.0)
</pre> </pre>Thanks, Nikolay!
Thanks, Nikolay! </dd>
</dd>
<dt>22 July 2003</dt> <dt>22 July 2003</dt>
<dd>Killed the dreaded "bad argument type for builtin operation" error. <dd>Killed the dreaded "bad argument type for builtin operation" error.
Argument errors now show the actual and expected argument types!</dd> Argument errors now show the actual and expected argument types!</dd>
<dt>19 July 2003</dt> <dt>19 July 2003</dt>
<dd>Added the new <code><a href= <dd>Added the new <code><a href=
"v2/return_arg.html">return_arg</a></code> policy from <a href= "v2/return_arg.html">return_arg</a></code> policy from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, "mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
Nikolay!</dd>
<dt>18 March, 2003</dt> <dt>18 March, 2003</dt>
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried <dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Gan&szlig;auge</a> has contributed <a href= Gan&szlig;auge</a> has contributed <a href=
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br> "v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a> <a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
has contributed the exciting <a href="../pyste/index.html">Pyste</a> Oliveira</a> has contributed the exciting <a href=
("Pie-steh") package.</dd> "../pyste/index.html">Pyste</a> ("Pie-steh") package.</dd>
<dt>24 February 2003</dt> <dt>24 February 2003</dt>
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now <dd>Finished improved support for <code>boost::shared_ptr</code>. Now any
any wrapped object of C++ class <code>X</code> can be converted wrapped object of C++ class <code>X</code> can be converted automatically
automatically to <code>shared_ptr&lt;X&gt;</code>, regardless of how it to <code>shared_ptr&lt;X&gt;</code>, regardless of how it was wrapped.
was wrapped. The <code>shared_ptr</code> will manage the lifetime of The <code>shared_ptr</code> will manage the lifetime of the Python object
the Python object which supplied the <code>X</code>, rather than just which supplied the <code>X</code>, rather than just the <code>X</code>
the <code>X</code> object itself, and when such a object itself, and when such a <code>shared_ptr</code> is converted back
<code>shared_ptr</code> is converted back to Python, the original to Python, the original Python object will be returned.</dd>
Python object will be returned.</dd>
<dt>19 January 2003</dt> <dt>19 January 2003</dt>
<dd>Integrated <code>staticmethod</code> support from <a href= <dd>Integrated <code>staticmethod</code> support from <a href=
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, "mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
Nikolay!</dd>
<dt>29 December 2002</dt> <dt>29 December 2002</dt>
<dd>Added Visual Studio project file and instructions from Brett <dd>Added Visual Studio project file and instructions from Brett Calcott.
Calcott. Thanks, Brett!</dd> Thanks, Brett!</dd>
<dt>20 December 2002</dt> <dt>20 December 2002</dt>
<dd>Added automatic downcasting for pointers, references, and smart <dd>Added automatic downcasting for pointers, references, and smart
pointers to polymorphic class types upon conversion to python</dd> pointers to polymorphic class types upon conversion to python</dd>
<dt>18 December 2002</dt> <dt>18 December 2002</dt>
<dd>Optimized from_python conversions for wrapped classes by putting <dd>Optimized from_python conversions for wrapped classes by putting the
the conversion logic in the shared library instead of registering conversion logic in the shared library instead of registering separate
separate converters for each class in each extension module</dd> converters for each class in each extension module</dd>
<dt>19 November 2002</dt> <dt>19 November 2002</dt>
<dd>Removed the need for users to cast base class member function <dd>Removed the need for users to cast base class member function
pointers when used as arguments to <a href= pointers when used as arguments to <a href=
"v2/class.html#class_-spec-modifiers">add_property</a></dd> "v2/class.html#class_-spec-modifiers">add_property</a></dd>
<dt>13 December 2002</dt> <dt>13 December 2002</dt>
<dd>Allow exporting of <a href= <dd>Allow exporting of <a href=
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing "v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br> <a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
Fixed unsigned integer conversions to deal correctly with numbers that Fixed unsigned integer conversions to deal correctly with numbers that
are out-of-range of <code>signed long</code>.</dd> are out-of-range of <code>signed long</code>.</dd>
<dt>14 November 2002</dt> <dt>14 November 2002</dt>
<dd>Auto-detection of class data members wrapped with <a href= <dd>Auto-detection of class data members wrapped with <a href=
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd> "v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
<dt>13 November 2002</dt> <dt>13 November 2002</dt>
<dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd> <dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd>
<dt>October 2002</dt> <dt>October 2002</dt>
<dd>Ongoing updates and improvements to tutorial documentation</dd> <dd>Ongoing updates and improvements to tutorial documentation</dd>
<dt>10 October 2002</dt> <dt>10 October 2002</dt>
<dd>Boost.Python V2 is released!</dd> <dd>Boost.Python V2 is released!</dd>
</dl> </dl>
<hr> <hr>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan --> <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
19 November 2004 19 November 2004
<!--webbot bot="Timestamp" endspan i-checksum="39359" --> <!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
</p>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave <p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003.</i></p> Abrahams</a> 2002-2003.</i></p>
</body> </body>
</html> </html>

View File

@@ -42,7 +42,7 @@
<dl class="page-index"> <dl class="page-index">
<dt><b><a href= <dt><b><a href=
"http://www.neuralynx.com/neuralab/index.htm">NeuraLab</a></b></dt> "http://www.neuralynx.com">NeuraLab</a></b></dt>
<dd>Neuralab is a data analysis environment specifically tailored for <dd>Neuralab is a data analysis environment specifically tailored for
neural data from <a href="http://www.neuralynx.com">Neuralynx</a> neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
@@ -351,13 +351,13 @@
<p>Two projects have been developed so far with this technology:</p> <p>Two projects have been developed so far with this technology:</p>
<p><b><a href="http://www.esss.com.br/dev_simba.phtml">Simba</a></b> <p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Simba</a></b>
provides 3D visualization of geological formations gattered from the provides 3D visualization of geological formations gattered from the
simulation of the evolution of oil systems, allowing the user to simulation of the evolution of oil systems, allowing the user to
analyse various aspects of the simulation, like deformation, pressure analyse various aspects of the simulation, like deformation, pressure
and fluids, along the time of the simulation.</p> and fluids, along the time of the simulation.</p>
<p><b><a href="http://www.esss.com.br/dev_aero.phtml">Aero</a></b> <p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Aero</a></b>
aims to construct a CFD with brazilian technology, which involves aims to construct a CFD with brazilian technology, which involves
various companies and universities. ESSS is responsible for various various companies and universities. ESSS is responsible for various
of the application modules, including GUI and post-processing of of the application modules, including GUI and post-processing of

View File

@@ -28,15 +28,13 @@
<div><div class="author"><h3 class="author"> <div><div class="author"><h3 class="author">
<span class="firstname">David</span> <span class="surname">Abrahams</span> <span class="firstname">David</span> <span class="surname">Abrahams</span>
</h3></div></div> </h3></div></div>
<div><p class="copyright">Copyright © 2002-2005 Joel de Guzman, David Abrahams</p></div> <div><p class="copyright">Copyright © 2002-2005 Joel
de Guzman, David Abrahams</p></div>
<div><div class="legalnotice"> <div><div class="legalnotice">
<a name="id442427"></a><p> <a name="id427816"></a><p>
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0. (See accompanying
(See accompanying file LICENSE_1_0.txt or copy at file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
<a href="http://www.boost.org/LICENSE_1_0.txt" target="_top"> http://www.boost.org/LICENSE_1_0.txt </a>)
http://www.boost.org/LICENSE_1_0.txt
</a>)
</p> </p>
</div></div> </div></div>
</div></div> </div></div>
@@ -85,47 +83,59 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.quickstart"></a>QuickStart</h2></div></div></div> <a name="python.quickstart"></a>QuickStart</h2></div></div></div>
<p> <p>
The Boost Python Library is a framework for interfacing Python and QuickStartThe Boost Python Library is a framework for interfacing Python and
C++. It allows you to quickly and seamlessly expose C++ classes C++. It allows you to quickly and seamlessly expose C++ classes functions and
functions and objects to Python, and vice-versa, using no special objects to Python, and vice-versa, using no special tools -- just your C++
tools -- just your C++ compiler. It is designed to wrap C++ interfaces compiler. It is designed to wrap C++ interfaces non-intrusively, so that you
non-intrusively, so that you should not have to change the C++ code at should not have to change the C++ code at all in order to wrap it, making Boost.Python
all in order to wrap it, making Boost.Python ideal for exposing ideal for exposing 3rd-party libraries to Python. The library's use of advanced
3rd-party libraries to Python. The library's use of advanced metaprogramming techniques simplifies its syntax for users, so that wrapping
metaprogramming techniques simplifies its syntax for users, so that code takes on the look of a kind of declarative interface definition language
wrapping code takes on the look of a kind of declarative interface (IDL).
definition language (IDL).</p> </p>
<a name="quickstart.hello_world"></a><h2> <a name="quickstart.hello_world"></a><h2>
<a name="id372086"></a>Hello World</h2> <a name="id372244"></a>
Hello World
</h2>
<p> <p>
Following C/C++ tradition, let's start with the "hello, world". A C++ Following C/C++ tradition, let's start with the "hello, world". A
Function:</p> C++ Function:
<pre class="programlisting"><tt class="literal"><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*</span><span class="identifier"> greet</span><span class="special">()</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
return</span><span class="string"> "hello, world"</span><span class="special">;</span><span class="special"> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">greet</span><span class="special">()</span>
}</span></tt></pre> <span class="special">{</span>
<span class="keyword">return</span> <span class="string">"hello, world"</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p> <p>
can be exposed to Python by writing a Boost.Python wrapper:</p> can be exposed to Python by writing a Boost.Python wrapper:
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword"> </p>
using</span><span class="keyword"> namespace</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span><span class="identifier"> <pre class="programlisting">
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span><span class="identifier"> greet</span><span class="special">);</span><span class="special"> <span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="identifier">greet</span><span class="special">);</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
That's it. We're done. We can now build this as a shared library. The That's it. We're done. We can now build this as a shared library. The resulting
resulting DLL is now visible to Python. Here's a sample Python session:</p> DLL is now visible to Python. Here's a sample Python session:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span>
hello</span><span class="special">,</span><span class="identifier"> world</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
</pre>
<p></p> <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><span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module
from start to finish...</b></span></em></span></p></blockquote></div>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><small><p>Last revised: July 12, 2005 at 07:50:43 GMT</p></small></td> <td align="left"><small><p>Last revised: October 31, 2005 at 18:46:06 GMT</p></small></td>
<td align="right"><small></small></td> <td align="right"><small></small></td>
</tr></table> </tr></table>
<hr> <hr>

View File

@@ -27,39 +27,47 @@
<a name="python.embedding"></a>Embedding</h2></div></div></div> <a name="python.embedding"></a>Embedding</h2></div></div></div>
<div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div> <div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div>
<p> <p>
By now you should know how to use Boost.Python to call your C++ code from EmbeddingBy now you should know how to use Boost.Python to call your C++ code
Python. However, sometimes you may need to do the reverse: call Python code from Python. However, sometimes you may need to do the reverse: call Python
from the C++-side. This requires you to <span class="emphasis"><em>embed</em></span> the Python interpreter code from the C++-side. This requires you to <span class="emphasis"><em>embed</em></span> the
into your C++ program.</p> Python interpreter into your C++ program.
</p>
<p> <p>
Currently, Boost.Python does not directly support everything you'll need Currently, Boost.Python does not directly support everything you'll need when
when embedding. Therefore you'll need to use the embedding. Therefore you'll need to use the <a href="http://www.python.org/doc/current/api/api.html" target="_top">Python/C
<a href="http://www.python.org/doc/current/api/api.html" target="_top">Python/C API</a> to fill in API</a> to fill in the gaps. However, Boost.Python already makes embedding
the gaps. However, Boost.Python already makes embedding a lot easier and, a lot easier and, in a future version, it may become unnecessary to touch the
in a future version, it may become unnecessary to touch the Python/C API at Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
<a name="embedding.building_embedded_programs"></a><h2> <a name="embedding.building_embedded_programs"></a><h2>
<a name="id456196"></a>Building embedded programs</h2> <a name="id457321"></a>
Building embedded programs
</h2>
<p> <p>
To be able to use embedding in your programs, they have to be linked to To be able to use embedding in your programs, they have to be linked to both
both Boost.Python's and Python's static link library.</p> Boost.Python's and Python's static link library.
</p>
<p> <p>
Boost.Python's static link library comes in two variants. Both are located 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 in Boost's <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On
variants are called <tt class="literal">boost_python.lib</tt> (for release builds) and Windows, the variants are called <tt class="literal">boost_python.lib</tt> (for release
<tt class="literal">boost_python_debug.lib</tt> (for debugging). If you can't find the libraries, builds) and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you
you probably haven't built Boost.Python yet. See 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> <a href="../../../../building.html" target="_top">Building and Testing</a> on how to
do this.
</p>
<p> <p>
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory of Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory
your Python directory. On Windows it is called pythonXY.lib where X.Y is of your Python directory. On Windows it is called pythonXY.lib where X.Y is
your major Python version number.</p> your major Python version number.
</p>
<p> <p>
Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added to your Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
include path.</p> to your include path.
</p>
<p> <p>
In a Jamfile, all the above boils down to:</p> In a Jamfile, all the above boils down to:
<pre class="programlisting"><tt class="literal">projectroot c:\projects\embedded_program ; # location of the program </p>
<pre class="programlisting">projectroot c:\projects\embedded_program ; # location of the program
# bring in the rules for python # bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ; SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
@@ -73,90 +81,121 @@ exe embedded_program # name of the executable
$(PYTHON_PROPERTIES) $(PYTHON_PROPERTIES)
&lt;library-path&gt;$(PYTHON_LIB_PATH) &lt;library-path&gt;$(PYTHON_LIB_PATH)
&lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ; &lt;find-library&gt;$(PYTHON_EMBEDDED_LIBRARY) ;
</tt></pre> </pre>
<a name="embedding.getting_started"></a><h2> <a name="embedding.getting_started"></a><h2>
<a name="id456277"></a>Getting started</h2> <a name="id457409"></a>
Getting started
</h2>
<p> <p>
Being able to build is nice, but there is nothing to build yet. Embedding Being able to build is nice, but there is nothing to build yet. Embedding the
the Python interpreter into one of your C++ programs requires these 4 Python interpreter into one of your C++ programs requires these 4 steps:
steps:</p> </p>
<div class="orderedlist"><ol type="1"> <div class="orderedlist"><ol type="1">
<li> <li>
#include <tt class="literal">&lt;boost/python.hpp&gt;</tt><br><br> #include <tt class="literal">&lt;boost/python.hpp&gt;</tt><br><br>
</li> </li>
<li> <li>
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>() to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt> module.<br><br> Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
module.<br><br>
</li> </li>
<li> <li>
Call other Python C API routines to use the interpreter.<br><br> Call other Python C API routines to use the interpreter.<br><br>
</li> </li>
<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. Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
</li> to stop the interpreter and release its resources.
</li>
</ol></div> </ol></div>
<p> <p>
(Of course, there can be other C++ code between all of these steps.)</p> (Of course, there can be other C++ code between all of these steps.)
<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> </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="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div> <a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
<p> <p>
As you probably already know, objects in Python are reference-counted. Using the interpreterAs you probably already know, objects in Python are
Naturally, the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted. reference-counted. Naturally, the <tt class="literal">PyObject</tt>s of the Python/C
There is a difference however. While the reference-counting is fully API are also reference-counted. There is a difference however. While the
automatic in Python, the Python/C API requires you to do it reference-counting is fully automatic in Python, the Python/C API requires
<a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by hand</a>. This is you to do it <a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by
messy and especially hard to get right in the presence of C++ exceptions. hand</a>. This is messy and especially hard to get right in the presence
Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a> and of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a>
<a href="../../../../v2/object.html" target="_top">object</a> class templates to automate the process.</p> 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="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
<a name="id456409"></a>Reference-counting handles and objects</h2> <a name="id457544"></a>
Reference-counting handles and objects
</h2>
<p> <p>
There are two ways in which a function in the Python/C API can return a 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 <tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span>
these a function uses, is listed in that function's documentation. The two or as a <span class="emphasis"><em>new reference</em></span>. Which of these a function uses,
require slightely different approaches to reference-counting but both can is listed in that function's documentation. The two require slightely different
be 'handled' by Boost.Python.</p> approaches to reference-counting but both can be 'handled' by Boost.Python.
</p>
<p> <p>
For a function returning a <span class="emphasis"><em>borrowed reference</em></span> we'll have to tell the For a function returning a <span class="emphasis"><em>borrowed reference</em></span> we'll
<tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt> is borrowed with the aptly named have to tell the <tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt>
<a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a> function. Two functions is borrowed with the aptly named <a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a>
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>. 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>
The former returns a reference to an already imported module, the latter and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594" target="_top">PyModule_GetDict</a>.
retrieves a module's namespace dictionary. Let's use them to retrieve the The former returns a reference to an already imported module, the latter
namespace of the <tt class="literal"><span class="underline">_main</span>_</tt> module:</p> retrieves a module's namespace dictionary. Let's use them to retrieve the
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier"> namespace of the <tt class="literal"><span class="underline">_main</span>_</tt>
handle</span><span class="special">&lt;&gt;(</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"> 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">&lt;&gt;(</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>
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></tt></pre> <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> <p>
For a function returning a <span class="emphasis"><em>new reference</em></span> we can just create a <tt class="literal">handle</tt> For a function returning a <span class="emphasis"><em>new reference</em></span> we can just
out of the raw <tt class="literal">PyObject*</tt> without wrapping it in a call to borrowed. One create a <tt class="literal">handle</tt> out of the raw <tt class="literal">PyObject*</tt>
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 without wrapping it in a call to borrowed. One such function that returns
discuss in the next section.</p> 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>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why haven't we been using any template parameters?</b></span><br><br><tt class="literal">handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt class="literal">PyObject</tt> 99% of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt> for convenience. Therefore we can use the shorthand <tt class="literal">handle&lt;&gt;</tt> instead of the longer, but equivalent, <tt class="literal">handle&lt;PyObject&gt;</tt>. <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why
</td></tr></tbody> 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&lt;&gt;</tt>
instead of the longer, but equivalent, <tt class="literal">handle&lt;PyObject&gt;</tt>.
</td></tr></tbody>
</table></div> </table></div>
<a name="using_the_interpreter.running_python_code"></a><h2> <a name="using_the_interpreter.running_python_code"></a><h2>
<a name="id456714"></a>Running Python code</h2> <a name="id457863"></a>
Running Python code
</h2>
<p> <p>
To run Python code from C++ there is a family of functions in the API To run Python code from C++ there is a family of functions in the API starting
starting with the PyRun prefix. You can find the full list of these 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
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:
all work similarly so we will look at only one of them, namely:</p> </p>
<pre class="programlisting"><tt class="literal"><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></tt></pre> <pre class="programlisting">
<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) <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>
string in its <tt class="literal">str</tt> parameter. The function returns a new reference to a </pre>
Python object. Which object is returned depends on the <tt class="literal">start</tt> paramater.</p> <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.
</p>
<p> <p>
The <tt class="literal">start</tt> parameter is the start symbol from the Python grammar to use The <tt class="literal">start</tt> parameter is the start symbol from the Python
for interpreting the code. The possible values are:</p> grammar to use for interpreting the code. The possible values are:
</p>
<div class="informaltable"> <div class="informaltable">
<h4> <h4>
<a name="id456876"></a><span class="table-title">Start symbols</span> <a name="id458033"></a><span class="table-title">Start symbols</span>
</h4> </h4>
<table class="table"> <table class="table">
<colgroup> <colgroup>
@@ -165,178 +204,215 @@ for interpreting the code. The possible values are:</p>
</colgroup> </colgroup>
<thead><tr> <thead><tr>
<th><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a></th> <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> <th>for
interpreting isolated expressions</th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<tr> <tr>
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a></td> <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> <td>for
interpreting sequences of statements</td>
</tr> </tr>
<tr> <tr>
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a></td> <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> <td>for
interpreting a single statement</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<p> <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 When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>,
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 the input string must contain a single expression and its result is returned.
contain an abitrary number of statements and None is returned. When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>,
<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 the string can contain an abitrary number of statements and None is returned.
single statement.</p> <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> <p>
Lastly, the <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters are Python dictionaries Lastly, the <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters
containing the globals and locals of the context in which to run the code. are Python dictionaries containing the globals and locals of the context
For most intents and purposes you can use the namespace dictionary of the in which to run the code. For most intents and purposes you can use the namespace
<tt class="literal"><span class="underline">_main</span>_</tt> module for both parameters.</p> dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
module for both parameters.
</p>
<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 We have already seen how to get the <tt class="literal"><span class="underline">_main</span>_</tt>
run some Python code in it:</p> module's namespace so let's run some Python code in it:
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier"> </p>
handle</span><span class="special">&lt;&gt;(</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"> <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">&lt;&gt;(</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>
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"> <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>
handle</span><span class="special">&lt;&gt;</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"> <span class="identifier">handle</span><span class="special">&lt;&gt;</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>
"hello = file('hello.txt', 'w')\n"</span><span class="string"> <span class="string">"hello = file('hello.txt', 'w')\n"</span>
"hello.write('Hello world!')\n"</span><span class="string"> <span class="string">"hello.write('Hello world!')\n"</span>
"hello.close()"</span><span class="special"> <span class="string">"hello.close()"</span>
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a><span class="special"> <span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special"> <span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span><span class="special"> <span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
));</span></tt></pre> <span class="special">));</span>
</pre>
<p> <p>
Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s, we used Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s,
the object's <tt class="literal">ptr</tt> member function to retrieve the <tt class="literal">PyObject*</tt>.</p> we used the object's <tt class="literal">ptr</tt> member function to retrieve the
<tt class="literal">PyObject*</tt>.
</p>
<p> <p>
This should create a file called 'hello.txt' in the current directory This should create a file called 'hello.txt' in the current directory containing
containing a phrase that is well-known in programming circles.</p> a phrase that is well-known in programming circles.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a> in a <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
(nameless) <tt class="literal">handle</tt> even though we are not interested in it. If we didn't in a (nameless) <tt class="literal">handle</tt> even though we are not interested
do this, the the returned object would be kept alive unnecessarily. Unless in it. If we didn't do this, the the returned object would be kept
you want to be a Dr. Frankenstein, always wrap <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s. alive unnecessarily. Unless you want to be a Dr. Frankenstein, always
</td></tr></tbody> wrap <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s.
</td></tr></tbody>
</table></div> </table></div>
<a name="using_the_interpreter.beyond_handles"></a><h2> <a name="using_the_interpreter.beyond_handles"></a><h2>
<a name="id457324"></a>Beyond handles</h2> <a name="id458506"></a>
Beyond handles
</h2>
<p> <p>
It's nice that <tt class="literal">handle</tt> manages the reference counting details for us, but It's nice that <tt class="literal">handle</tt> manages the reference counting details
other than that it doesn't do much. Often we'd like to have a more useful for us, but other than that it doesn't do much. Often we'd like to have a
class to manipulate Python objects. But we have already seen such a class more useful class to manipulate Python objects. But we have already seen
above, and in the <a href="object.html" target="_top">previous section</a>: the aptly such a class above, and in the <a href="object.html" target="_top">previous section</a>:
named <tt class="literal">object</tt> class and it's derivatives. We've already seen that they the aptly named <tt class="literal">object</tt> class and it's derivatives. We've
can be constructed from a <tt class="literal">handle</tt>. The following examples should further already seen that they can be constructed from a <tt class="literal">handle</tt>.
illustrate this fact:</p> The following examples should further illustrate this fact:
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> main_module</span><span class="special">((</span><span class="identifier"> </p>
handle</span><span class="special">&lt;&gt;(</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"> <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">&lt;&gt;(</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>
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"> <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>
handle</span><span class="special">&lt;&gt;</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"> <span class="identifier">handle</span><span class="special">&lt;&gt;</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>
"result = 5 ** 2"</span><span class="special"> <span class="string">"result = 5 ** 2"</span>
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a><span class="special"> <span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special"> <span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span><span class="special"> <span class="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
));</span><span class="keyword"> <span class="special">));</span>
int</span><span class="identifier"> five_squared</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span></tt></pre> <span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
</pre>
<p> <p>
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt> module's namespace. Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
Then we assign 5 squared to the result variable and read this variable from module's namespace. Then we assign 5 squared to the result variable and read
the dictionary. Another way to achieve the same result is to let this variable from the dictionary. Another way to achieve the same result
<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>:</p> is to let <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">handle</span><span class="special">&lt;&gt;(</span> return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>:
    <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"> </p>
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special"> <pre class="programlisting">
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special"> <span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special">&lt;&gt;(</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span><span class="special"> <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><span class="keyword"> <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>
int</span><span class="identifier"> five_squared</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span></tt></pre> <span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span>
</pre>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member function to return the wrapped <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member
<tt class="literal">PyObject*</tt> is called <tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes sense if you function to return the wrapped <tt class="literal">PyObject*</tt> is called
take into account the different functions that <tt class="literal">object</tt> and <tt class="literal">handle</tt> <tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes
perform. sense if you take into account the different functions that <tt class="literal">object</tt>
</td></tr></tbody> and <tt class="literal">handle</tt> perform. </td></tr></tbody>
</table></div> </table></div>
<a name="using_the_interpreter.exception_handling"></a><h2> <a name="using_the_interpreter.exception_handling"></a><h2>
<a name="id457906"></a>Exception handling</h2> <a name="id459120"></a>
Exception handling
</h2>
<p> <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> 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 function returns a null pointer. Constructing a <tt class="literal">handle</tt>
pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>, 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 so basically, the Python exception is automatically translated into a C++
C++ exception when using <tt class="literal">handle</tt>:</p> exception when using <tt class="literal">handle</tt>:
<pre class="programlisting"><tt class="literal"><span class="keyword">try</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
object</span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">handle</span><span class="special">&lt;&gt;(</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"> <span class="keyword">try</span>
"5/0"</span><span class="special"> <span class="special">{</span>
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special"> <span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special">&lt;&gt;(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special"> <span class="string">"5/0"</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span><span class="special"> <span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
));</span><span class="comment"> <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>
// execution will never get here: <span class="comment">// execution will never get here:
</span><span class="keyword"> int</span><span class="identifier"> five_divided_by_zero</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span><span class="special"> </span> <span class="keyword">int</span> <span class="identifier">five_divided_by_zero</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">result</span><span class="special">);</span>
}</span><span class="keyword"> <span class="special">}</span>
catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span><span class="special"> <span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
// handle the exception in some way <span class="comment">// handle the exception in some way
</span><span class="special">}</span></tt></pre> </span><span class="special">}</span>
</pre>
<p> <p>
The <tt class="literal">error_already_set</tt> exception class doesn't carry any information in itself. The <tt class="literal">error_already_set</tt> exception class doesn't carry any
To find out more about the Python exception that occurred, you need to use the information in itself. To find out more about the Python exception that occurred,
<a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception handling functions</a> you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
of the Python/C API in your catch-statement. This can be as simple as calling handling functions</a> of the Python/C API in your catch-statement. This
<a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a> to can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a>
print the exception's traceback to the console, or comparing the type of the to print the exception's traceback to the console, or comparing the type
exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard exceptions</a>:</p> of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
<pre class="programlisting"><tt class="literal"><span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span><span class="special"> exceptions</a>:
{</span><span class="keyword"> </p>
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"> <pre class="programlisting">
{</span><span class="comment"> <span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
// handle ZeroDivisionError specially <span class="special">{</span>
</span><span class="special"> }</span><span class="keyword"> <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>
else</span><span class="special"> <span class="special">{</span>
{</span><span class="comment"> <span class="comment">// handle ZeroDivisionError specially
// print all other errors to stderr </span> <span class="special">}</span>
</span><span class="identifier"> PyErr_Print</span><span class="special">();</span><span class="special"> <span class="keyword">else</span>
}</span><span class="special"> <span class="special">{</span>
}</span></tt></pre> <span class="comment">// print all other errors to stderr
</span> <span class="identifier">PyErr_Print</span><span class="special">();</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p> <p>
(To retrieve even more information from the exception you can use some of the other (To retrieve even more information from the exception you can use some of
exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)</p> the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)
</p>
<p> <p>
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception when it is constructed, you If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception
can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a> function in the same when it is constructed, you can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a>
way you'd use borrowed:</p> function in the same way you'd use borrowed:
<pre class="programlisting"><tt class="literal"><span class="identifier">handle</span><span class="special">&lt;&gt;</span><span class="identifier"> result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><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"> </p>
"5/0"</span><span class="special"> <pre class="programlisting">
,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a><span class="special"> <span class="identifier">handle</span><span class="special">&lt;&gt;</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()</span><span class="special"> <span class="string">"5/0"</span>
,</span><span class="identifier"> main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))));</span><span class="keyword"> <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>
if</span><span class="special"> (!</span><span class="identifier">result</span><span class="special">)</span><span class="comment"> <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">result</span><span class="special">)</span>
// Python exception occurred <span class="comment">// Python exception occurred
</span><span class="keyword">else</span><span class="comment"> </span><span class="keyword">else</span>
// everything went okay, it's safe to use the result <span class="comment">// everything went okay, it's safe to use the result
</span></tt></pre> </span></pre>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -26,25 +26,32 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.exception"></a> Exception Translation</h2></div></div></div> <a name="python.exception"></a> Exception Translation</h2></div></div></div>
<p> <p>
All C++ exceptions must be caught at the boundary with Python code. This Exception TranslationAll C++ exceptions must be caught at the boundary with
boundary is the point where C++ meets Python. Boost.Python provides a Python code. This boundary is the point where C++ meets Python. Boost.Python
default exception handler that translates selected standard exceptions, provides a default exception handler that translates selected standard exceptions,
then gives up:</p> then gives up:
<pre class="programlisting"><tt class="literal"><span class="identifier">raise</span><span class="identifier"> RuntimeError</span><span class="special">,</span><span class="char"> 'unidentifiable C++ Exception'</span></tt></pre> </p>
<pre class="programlisting">
<span class="keyword">raise</span> <span class="identifier">RuntimeError</span><span class="special">,</span> <span class="string">'unidentifiable C++ Exception'</span>
</pre>
<p> <p>
Users may provide custom translation. Here's an example:</p> Users may provide custom translation. Here's an example:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> PodBayDoorException</span><span class="special">;</span><span class="keyword"> </p>
void</span><span class="identifier"> translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span><span class="keyword"> const</span><span class="special">&amp;</span><span class="identifier"> x</span><span class="special">)</span><span class="special"> {</span><span class="identifier"> <pre class="programlisting">
PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span><span class="string"> "I'm sorry Dave..."</span><span class="special">);</span><span class="special"> <span class="identifier">struct</span> <span class="identifier">PodBayDoorException</span><span class="special">;</span>
}</span><span class="identifier"> <span class="identifier">void</span> <span class="identifier">translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span> <span class="identifier">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">kubrick</span><span class="special">)</span><span class="special"> {</span><span class="identifier"> <span class="identifier">PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span> <span class="string">"I'm sorry Dave..."</span><span class="special">);</span>
register_exception_translator</span><span class="special">&lt;</span><span class="identifier"> <span class="special">}</span>
PodBayDoorException</span><span class="special">&gt;(</span><span class="identifier">translator</span><span class="special">);</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">kubrick</span><span class="special">)</span> <span class="special">{</span>
...</span></tt></pre> <span class="identifier">register_exception_translator</span><span class="special">&lt;</span>
<span class="identifier">PodBayDoorException</span><span class="special">&gt;(</span><span class="identifier">translator</span><span class="special">);</span>
<span class="special">...</span>
</pre>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -35,284 +35,373 @@
<dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt> <dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
</dl></div> </dl></div>
<p> <p>
Now let's expose a C++ class to Python.</p> Exposing ClassesNow let's expose a C++ class to Python.
</p>
<p> <p>
Consider a C++ class/struct that we want to expose to Python:</p> Consider a C++ class/struct that we want to expose to Python:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> World</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
void</span><span class="identifier"> set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">)</span><span class="special"> {</span><span class="keyword"> this</span><span class="special">-&gt;</span><span class="identifier">msg</span><span class="special"> =</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> }</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">World</span>
std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> greet</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> }</span><span class="identifier"> <span class="special">{</span>
std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
};</span></tt></pre> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p> <p>
We can expose this to Python by writing a corresponding Boost.Python We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:
C++ Wrapper:</p> </p>
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword"> <pre class="programlisting">
using</span><span class="keyword"> namespace</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span><span class="identifier"> <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">)</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
;</span><span class="special"> <span class="special">;</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
Here, we wrote a C++ class wrapper that exposes the member functions Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
<tt class="literal">greet</tt> and <tt class="literal">set</tt>. Now, after building our module as a shared library, we and <tt class="literal">set</tt>. Now, after building our module as a shared library,
may use our class <tt class="literal">World</tt> in Python. Here's a sample Python session:</p> we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
session:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span>
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="string"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span>
'howdy'</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
<span class="string">'howdy'</span>
</pre>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.constructors"></a>Constructors</h3></div></div></div> <a name="python.constructors"></a>Constructors</h3></div></div></div>
<p> <p>
Our previous example didn't have any explicit constructors. ConstructorsOur previous example didn't have any explicit constructors. Since
Since <tt class="literal">World</tt> is declared as a plain struct, it has an implicit default <tt class="literal">World</tt> is declared as a plain struct, it has an implicit
constructor. Boost.Python exposes the default constructor by default, default constructor. Boost.Python exposes the default constructor by default,
which is why we were able to write</p> which is why we were able to write
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> planet</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span></tt></pre> </p>
<pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
</pre>
<p> <p>
We may wish to wrap a class with a non-default constructor. Let us We may wish to wrap a class with a non-default constructor. Let us build
build on our previous example:</p> on our previous example:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> World</span><span class="special"> <pre class="programlisting">
{</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">World</span>
World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">):</span><span class="identifier"> msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span><span class="special"> {}</span><span class="comment"> // added constructor <span class="special">{</span>
</span><span class="keyword"> void</span><span class="identifier"> set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">)</span><span class="special"> {</span><span class="keyword"> this</span><span class="special">-&gt;</span><span class="identifier">msg</span><span class="special"> =</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> }</span><span class="identifier"> <span class="identifier">World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">):</span> <span class="identifier">msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span> <span class="special">{}</span> <span class="comment">// added constructor
std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> greet</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> }</span><span class="identifier"> </span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> msg</span><span class="special">;</span><span class="special"> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
};</span></tt></pre> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p> <p>
This time <tt class="literal">World</tt> has no default constructor; our previous This time <tt class="literal">World</tt> has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose wrapping code would fail to compile when the library tried to expose it.
it. We have to tell <tt class="literal">class_&lt;World&gt;</tt> about the constructor we want to We have to tell <tt class="literal">class_&lt;World&gt;</tt> about the constructor
expose instead.</p> we want to expose instead.
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword"> </p>
using</span><span class="keyword"> namespace</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span><span class="identifier"> <pre class="programlisting">
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
;</span><span class="special"> <span class="special">;</span>
}</span></tt></pre> <span class="special">}</span>
<p><tt class="literal">init&lt;std::string&gt;()</tt> exposes the constructor taking in a </pre>
<tt class="literal">std::string</tt> (in Python, constructors are spelled <p><tt class="literal">init&lt;std::string&gt;()</tt> exposes the constructor taking
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").</p> in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
</p>
<p> <p>
We can expose additional constructors by passing more <tt class="literal">init&lt;...&gt;</tt>s to We can expose additional constructors by passing more <tt class="literal">init&lt;...&gt;</tt>s
the <tt class="literal">def()</tt> member function. Say for example we have another World to the <tt class="literal">def()</tt> member function. Say for example we have
constructor taking in two doubles:</p> another World constructor taking in two doubles:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</span><span class="special">&gt;())</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
;</span></tt></pre> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p> <p>
On the other hand, if we do not wish to expose any constructors at On the other hand, if we do not wish to expose any constructors at all, we
all, we may use <tt class="literal">no_init</tt> instead:</p> may use <tt class="literal">no_init</tt> instead:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span><span class="identifier"> no_init</span><span class="special">)</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
</pre>
<p> <p>
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt> method which always raises a This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
Python RuntimeError exception.</p> method which always raises a Python RuntimeError exception.
</p>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div> <a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
<p> <p>
Data members may also be exposed to Python so that they can be Class Data MembersData members may also be exposed to Python so that they
accessed as attributes of the corresponding Python class. Each data 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 member that we wish to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
<span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:</p> or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Var</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> name</span><span class="special">)</span><span class="special"> :</span><span class="identifier"> name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span><span class="identifier"> value</span><span class="special">()</span><span class="special"> {}</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">Var</span>
std</span><span class="special">::</span><span class="identifier">string</span><span class="keyword"> const</span><span class="identifier"> name</span><span class="special">;</span><span class="keyword"> <span class="special">{</span>
float</span><span class="identifier"> value</span><span class="special">;</span><span class="special"> <span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span>
};</span></tt></pre> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span>
<span class="keyword">float</span> <span class="identifier">value</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p> <p>
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed to Python:</p> Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span><span class="identifier"> init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span><span class="special"> to Python:
.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span></tt></pre> <pre class="programlisting">
<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span>
</pre>
<p> <p>
Then, in Python, assuming we have placed our Var class inside the namespace Then, in Python, assuming we have placed our Var class inside the namespace
hello as we did before:</p> hello as we did before:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special"> =</span><span class="number"> 3.14</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span>
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span><span class="string"> 'is around'</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
pi</span><span class="keyword"> is</span><span class="identifier"> around</span><span class="number"> 3.14</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span> <span class="string">'is around'</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span>
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
</pre>
<p> <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 Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
as <span class="bold"><b>read-write</b></span>.</p> while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</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 </p>
</span><span class="identifier">Traceback</span><span class="special"> (</span><span class="identifier">most</span><span class="identifier"> recent</span><span class="identifier"> call</span><span class="identifier"> last</span><span class="special">):</span><span class="identifier"> <pre class="programlisting">
File</span><span class="string"> "&lt;stdin&gt;"</span><span class="special">,</span><span class="identifier"> line</span><span class="number"> 1</span><span class="special">,</span><span class="keyword"> in</span>#<span class="identifier"> <span class="special">&gt;&gt;&gt;</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
AttributeError</span><span class="special">:</span><span class="identifier"> can</span>#<span class="identifier">t</span><span class="identifier"> set</span><span class="identifier"> attribute</span></tt></pre> </span><span class="identifier">Traceback</span> <span class="special">(</span><span class="identifier">most</span> <span class="identifier">recent</span> <span class="identifier">call</span> <span class="identifier">last</span><span class="special">):</span>
<span class="identifier">File</span> <span class="string">"&lt;stdin&gt;"</span><span class="special">,</span> <span class="identifier">line</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">in</span> #
<span class="identifier">AttributeError</span><span class="special">:</span> <span class="identifier">can</span>#<span class="identifier">t</span> <span class="identifier">set</span> <span class="identifier">attribute</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_properties"></a>Class Properties</h3></div></div></div> <a name="python.class_properties"></a>Class Properties</h3></div></div></div>
<p> <p>
In C++, classes with public data members are usually frowned Class PropertiesIn C++, classes with public data members are usually frowned
upon. Well designed classes that take advantage of encapsulation hide upon. Well designed classes that take advantage of encapsulation hide the
the class' data members. The only way to access the class' data is class' data members. The only way to access the class' data is through access
through access (getter/setter) functions. Access functions expose class (getter/setter) functions. Access functions expose class properties. Here's
properties. Here's an example:</p> an example:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Num</span><span class="special"> <pre class="programlisting">
{</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">Num</span>
Num</span><span class="special">();</span><span class="keyword"> <span class="special">{</span>
float</span><span class="identifier"> get</span><span class="special">()</span><span class="keyword"> const</span><span class="special">;</span><span class="keyword"> <span class="identifier">Num</span><span class="special">();</span>
void</span><span class="identifier"> set</span><span class="special">(</span><span class="keyword">float</span><span class="identifier"> value</span><span class="special">);</span><span class="special"> <span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
...</span><span class="special"> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">value</span><span class="special">);</span>
};</span></tt></pre> <span class="special">...</span>
<span class="special">};</span>
</pre>
<p> <p>
However, in Python attribute access is fine; it doesn't neccessarily break However, in Python attribute access is fine; it doesn't neccessarily break
encapsulation to let users handle attributes directly, because the encapsulation to let users handle attributes directly, because the attributes
attributes can just be a different syntax for a method call. Wrapping our can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
<tt class="literal">Num</tt> class using Boost.Python:</p> class using Boost.Python:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span></tt></pre> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span>
</pre>
<p> <p>
And at last, in Python:</p> And at last, in Python:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> Num</span><span class="special">()</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special"> =</span><span class="number"> 3.14</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span>
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
(</span><span class="number">3.14</span><span class="special">,</span><span class="number"> 3.14</span><span class="special">)</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span>
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">rovalue</span><span class="special"> =</span><span class="number"> 2.17</span><span class="comment"> # error! <span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">3.14</span><span class="special">)</span>
</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
</span></pre>
<p> <p>
Take note that the class property <tt class="literal">rovalue</tt> is exposed as <span class="bold"><b>read-only</b></span> Take note that the class property <tt class="literal">rovalue</tt> is exposed as
since the <tt class="literal">rovalue</tt> setter member function is not passed in:</p> <span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
setter member function is not passed in:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span></tt></pre> <pre class="programlisting">
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.inheritance"></a>Inheritance</h3></div></div></div> <a name="python.inheritance"></a>Inheritance</h3></div></div></div>
<p> <p>
In the previous examples, we dealt with classes that are not polymorphic. InheritanceIn the previous examples, we dealt with classes that are not polymorphic.
This is not often the case. Much of the time, we will be wrapping This is not often the case. Much of the time, we will be wrapping polymorphic
polymorphic classes and class hierarchies related by inheritance. We will classes and class hierarchies related by inheritance. We will often have
often have to write Boost.Python wrappers for classes that are derived from to write Boost.Python wrappers for classes that are derived from abstract
abstract base classes.</p> base classes.
</p>
<p> <p>
Consider this trivial inheritance structure:</p> Consider this trivial inheritance structure:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special"> {</span><span class="keyword"> virtual</span><span class="special"> ~</span><span class="identifier">Base</span><span class="special">();</span><span class="special"> };</span><span class="keyword"> </p>
struct</span><span class="identifier"> Derived</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special"> {};</span></tt></pre> <pre class="programlisting">
<span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
</pre>
<p> <p>
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt> object And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
instances:</p> object instances:
<pre class="programlisting"><tt class="literal"><span class="keyword">void</span><span class="identifier"> b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span><span class="keyword"> </p>
void</span><span class="identifier"> d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span><span class="identifier"> <pre class="programlisting">
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></tt></pre> <span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span>
<span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span>
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
</pre>
<p> <p>
We've seen how we can wrap the base class <tt class="literal">Base</tt>:</p> We've seen how we can wrap the base class <tt class="literal">Base</tt>:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span><span class="comment"> </p>
/*...*/</span><span class="special"> <pre class="programlisting">
;</span></tt></pre> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="comment">/*...*/</span>
<span class="special">;</span>
</pre>
<p> <p>
Now we can inform Boost.Python of the inheritance relationship between Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
<tt class="literal">Derived</tt> and its base class <tt class="literal">Base</tt>. Thus:</p> and its base class <tt class="literal">Base</tt>. Thus:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span><span class="special"> &gt;(</span><span class="string">"Derived"</span><span class="special">)</span><span class="comment"> </p>
/*...*/</span><span class="special"> <pre class="programlisting">
;</span></tt></pre> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span>
<span class="comment">/*...*/</span>
<span class="special">;</span>
</pre>
<p> <p>
Doing so, we get some things for free:</p> Doing so, we get some things for free:
</p>
<div class="orderedlist"><ol type="1"> <div class="orderedlist"><ol type="1">
<li> <li>
Derived automatically inherits all of Base's Python methods Derived automatically inherits all of Base's Python methods (wrapped C++
(wrapped C++ member functions) member functions)
</li> </li>
<li> <li>
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt> objects which have been passed to <span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
Python via a pointer or reference to <tt class="literal">Base</tt> can be passed where a pointer objects which have been passed to Python via a pointer or reference to
or reference to <tt class="literal">Derived</tt> is expected. <tt class="literal">Base</tt> can be passed where a pointer or reference to
</li> <tt class="literal">Derived</tt> is expected.
</li>
</ol></div> </ol></div>
<p> <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>:</p> Now, we shall expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
<pre class="programlisting"><tt class="literal"><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><span class="identifier"> and <tt class="literal">factory</tt>:
def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span><span class="identifier"> d</span><span class="special">);</span><span class="identifier"> </p>
def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span><span class="identifier"> factory</span><span class="special">);</span></tt></pre> <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>
<span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
</pre>
<p> <p>
Note that free function <tt class="literal">factory</tt> is being used to generate new Note that free function <tt class="literal">factory</tt> is being used to generate
instances of class <tt class="literal">Derived</tt>. In such cases, we use new instances of class <tt class="literal">Derived</tt>. In such cases, we use
<tt class="literal">return_value_policy&lt;manage_new_object&gt;</tt> to instruct Python to adopt <tt class="literal">return_value_policy&lt;manage_new_object&gt;</tt> to instruct
the pointer to <tt class="literal">Base</tt> and hold the instance in a new Python <tt class="literal">Base</tt> Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
object until the the Python object is destroyed. We shall see more of in a new Python <tt class="literal">Base</tt> object until the the Python object
Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call policies</a> later.</p> is destroyed. We shall see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
<pre class="programlisting"><tt class="literal"><span class="comment">// Tell Python to take ownership of factory's result policies</a> later.
</span><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><span class="identifier"> </p>
return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span></tt></pre> <pre class="programlisting">
<span class="comment">// Tell Python to take ownership of factory's result
</span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span>
<span class="identifier">return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div> <a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
<p> <p>
In this section, we shall learn how to make functions behave polymorphically Class Virtual FunctionsIn this section, we shall learn how to make functions
through virtual functions. Continuing our example, let us add a virtual function behave polymorphically through virtual functions. Continuing our example,
to our <tt class="literal">Base</tt> class:</p> let us add a virtual function to our <tt class="literal">Base</tt> class:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
virtual</span><span class="special"> ~</span><span class="identifier">Base</span><span class="special">()</span><span class="special"> {}</span><span class="keyword"> <span class="keyword">struct</span> <span class="identifier">Base</span>
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> =</span><span class="number"> 0</span><span class="special">;</span><span class="special"> <span class="special">{</span>
};</span></tt></pre> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p> <p>
One of the goals of Boost.Python is to be minimally intrusive on an existing C++ One of the goals of Boost.Python is to be minimally intrusive on an existing
design. In principle, it should be possible to expose the interface for a 3rd C++ design. In principle, it should be possible to expose the interface for
party library without changing it. It is not ideal to add anything to our class a 3rd party library without changing it. It is not ideal to add anything
<tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when you have a virtual function that's going to be overridden in to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
Python and called polymorphically <span class="bold"><b>from C++</b></span>, we'll need to add some you have a virtual function that's going to be overridden in Python and called
scaffoldings to make things work properly. What we'll do is write a class polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt> that will unintrusively hook into the virtual add some scaffoldings to make things work properly. What we'll do is write
functions so that a Python override may be called:</p> a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">,</span><span class="identifier"> wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span><span class="special"> that will unintrusively hook into the virtual functions so that a Python
{</span><span class="keyword"> override may be called:
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
return</span><span class="keyword"> this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span><span class="special"> <span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
}</span><span class="special"> <span class="special">{</span>
};</span></tt></pre> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p> <p>
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>, we also multiply- Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>). The we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
<tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes the job of wrapping classes that are meant to The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
overridden in Python, easier.</p> the job of wrapping classes that are meant to overridden in Python, easier.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> <span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> If you are using
Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt>
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">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody> as:<br><br><tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
</table></div> </table></div>
<p> <p>
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt> in effect calls the BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.</p> in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
</p>
<p> <p>
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:</p> Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span><span class="special"> <pre class="programlisting">
;</span></tt></pre> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<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 pure virtual <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span>
function.</p> <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
pure virtual function.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>member function and methods</b></span><br><br> <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>member function and methods</b></span><br><br> Python,
Python, like like many object oriented languages uses the term <span class="bold"><b>methods</b></span>.
many object oriented languages uses the term <span class="bold"><b>methods</b></span>. Methods Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
</td></tr></tbody> </td></tr></tbody>
</table></div> </table></div>
</div> </div>
@@ -320,153 +409,196 @@ correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
<div class="titlepage"><div><div><h3 class="title"> <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> <a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
<p> <p>
We've seen in the previous section how classes with pure virtual functions are Virtual Functions with Default ImplementationsWe've seen in the previous
wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class wrapper</a> section how classes with pure virtual functions are wrapped using Boost.Python's
facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions instead, the <a href="../../../../v2/wrapper.html" target="_top">class wrapper</a> facilities. If
mechanism is a bit different.</p> we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions
instead, the mechanism is a bit different.
</p>
<p> <p>
Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous section</a>, we Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous
wrapped a class with a pure virtual function that we then implemented in C++, or section</a>, we wrapped a class with a pure virtual function that we then
Python classes derived from it. Our base class:</p> implemented in C++, or Python classes derived from it. Our base class:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> =</span><span class="number"> 0</span><span class="special">;</span><span class="special"> <span class="keyword">struct</span> <span class="identifier">Base</span>
};</span></tt></pre> <span class="special">{</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p> <p>
had a pure virtual function <tt class="literal">f</tt>. If, however, its member function <tt class="literal">f</tt> was had a pure virtual function <tt class="literal">f</tt>. If, however, its member
not declared as pure virtual:</p> function <tt class="literal">f</tt> was not declared as pure virtual:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Base</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
virtual</span><span class="special"> ~</span><span class="identifier">Base</span><span class="special">()</span><span class="special"> {}</span><span class="keyword"> <span class="keyword">struct</span> <span class="identifier">Base</span>
virtual</span><span class="keyword"> int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="number"> 0</span><span class="special">;</span><span class="special"> }</span><span class="special"> <span class="special">{</span>
};</span></tt></pre> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<p> <p>
We wrap it this way:</p> We wrap it this way:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> BaseWrap</span><span class="special"> :</span><span class="identifier"> Base</span><span class="special">,</span><span class="identifier"> wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
int</span><span class="identifier"> f</span><span class="special">()</span><span class="special"> <span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
{</span><span class="keyword"> <span class="special">{</span>
if</span><span class="special"> (</span><span class="identifier">override</span><span class="identifier"> f</span><span class="special"> =</span><span class="keyword"> this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span><span class="keyword"> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
return</span><span class="identifier"> f</span><span class="special">();</span><span class="comment"> // *note* <span class="special">{</span>
</span><span class="keyword"> return</span><span class="identifier"> Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special"> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">override</span> <span class="identifier">f</span> <span class="special">=</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span>
}</span><span class="keyword"> <span class="keyword">return</span> <span class="identifier">f</span><span class="special">();</span> <span class="comment">// *note*
</span> <span class="keyword">return</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span>
<span class="special">}</span>
int</span><span class="identifier"> default_f</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="keyword"> this</span><span class="special">-&gt;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span><span class="special"> }</span><span class="special"> <span class="keyword">int</span> <span class="identifier">default_f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span> <span class="special">}</span>
};</span></tt></pre> <span class="special">};</span>
</pre>
<p> <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 Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
override for <tt class="computeroutput"><span class="identifier">f</span></tt>. If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.</p> we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> <span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> If you are using
Microsoft Visual C++ 6 or 7, you have to rewrite the line with the
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line <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">&lt;</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<br><br><tt class="computeroutput"><span class="keyword">return</span><span class="identifier"> call</span><span class="special">&lt;</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
</table></div> </table></div>
<p> <p>
Finally, exposing:</p> Finally, exposing:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span><span class="special"> <pre class="programlisting">
;</span></tt></pre> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p> <p>
Take note that we expose both <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Take note that we expose both <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
Boost.Python needs to keep track of 1) the dispatch function <tt class="literal">f</tt> and 2) the of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
forwarding function to its default implementation <tt class="literal">default_f</tt>. There's a to its default implementation <tt class="literal">default_f</tt>. There's a special
special <tt class="literal">def</tt> function for this purpose.</p> <tt class="literal">def</tt> function for this purpose.
</p>
<p> <p>
In Python, the results would be as expected:</p> In Python, the results would be as expected:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> base</span><span class="special"> =</span><span class="identifier"> Base</span><span class="special">()</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="keyword"> class</span><span class="identifier"> Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span> <span class="special">=</span> <span class="identifier">Base</span><span class="special">()</span>
...</span><span class="keyword"> def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">class</span> <span class="identifier">Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span>
...</span><span class="keyword"> return</span><span class="number"> 42</span><span class="special"> <span class="special">...</span> <span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
...</span><span class="special"> <span class="special">...</span> <span class="keyword">return</span> <span class="number">42</span>
&gt;&gt;&gt;</span><span class="identifier"> derived</span><span class="special"> =</span><span class="identifier"> Derived</span><span class="special">()</span></tt></pre> <span class="special">...</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
</pre>
<p> <p>
Calling <tt class="literal">base.f()</tt>:</p> Calling <tt class="literal">base.f()</tt>:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number"> </p>
0</span></tt></pre> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">0</span>
</pre>
<p> <p>
Calling <tt class="literal">derived.f()</tt>:</p> Calling <tt class="literal">derived.f()</tt>:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span><span class="number"> </p>
42</span></tt></pre> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
<span class="number">42</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <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="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="class_operators_special_functions.class_operators_special_functionspython_operators"></a><h2>
<a name="id447543"></a>Python Operators</h2> <a name="id447955"></a>
Class Operators/Special FunctionsPython Operators
</h2>
<p> <p>
C is well known for the abundance of operators. C++ extends this to the C is well known for the abundance of operators. C++ extends this to the extremes
extremes by allowing operator overloading. Boost.Python takes advantage of by allowing operator overloading. Boost.Python takes advantage of this and
this and makes it easy to wrap C++ operator-powered classes.</p> makes it easy to wrap C++ operator-powered classes.
</p>
<p> <p>
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators that take Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
on FilePos instances:</p> that take on FilePos instances:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> FilePos</span><span class="special"> {</span><span class="comment"> /*...*/</span><span class="special"> };</span><span class="identifier"> <pre class="programlisting">
<span class="keyword">class</span> <span class="identifier">FilePos</span> <span class="special">{</span> <span class="comment">/*...*/</span> <span class="special">};</span>
FilePos</span><span class="keyword"> operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span><span class="keyword"> int</span><span class="special">);</span><span class="identifier"> <span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
FilePos</span><span class="keyword"> operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span><span class="identifier"> FilePos</span><span class="special">);</span><span class="keyword"> <span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
int</span><span class="keyword"> operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span><span class="identifier"> FilePos</span><span class="special">);</span><span class="identifier"> <span class="keyword">int</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
FilePos</span><span class="keyword"> operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span><span class="keyword"> int</span><span class="special">);</span><span class="identifier"> <span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
FilePos</span><span class="special">&amp;</span><span class="keyword"> operator</span><span class="special">+=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span><span class="keyword"> int</span><span class="special">);</span><span class="identifier"> <span class="identifier">FilePos</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
FilePos</span><span class="special">&amp;</span><span class="keyword"> operator</span><span class="special">-=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span><span class="keyword"> int</span><span class="special">);</span><span class="keyword"> <span class="identifier">FilePos</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
bool</span><span class="keyword"> operator</span><span class="special">&lt;(</span><span class="identifier">FilePos</span><span class="special">,</span><span class="identifier"> FilePos</span><span class="special">);</span></tt></pre> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
</pre>
<p> <p>
The class and the various operators can be mapped to Python rather easily The class and the various operators can be mapped to Python rather easily
and intuitively:</p> and intuitively:
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> +</span><span class="keyword"> int</span><span class="special">())</span><span class="comment"> // __add__ <pre class="programlisting">
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span><span class="special"> +</span><span class="identifier"> self</span><span class="special">)</span><span class="comment"> // __radd__ <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span>
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> -</span><span class="identifier"> self</span><span class="special">)</span><span class="comment"> // __sub__ <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __add__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> -</span><span class="keyword"> int</span><span class="special">())</span><span class="comment"> // __sub__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __radd__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> +=</span><span class="keyword"> int</span><span class="special">())</span><span class="comment"> // __iadd__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __sub__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> -=</span><span class="identifier"> other</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;())</span><span class="special"> </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __sub__
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span><span class="special"> &lt;</span><span class="identifier"> self</span><span class="special">);</span><span class="comment"> // __lt__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+=</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __iadd__
</span></tt></pre> </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-=</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;())</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">&lt;</span> <span class="identifier">self</span><span class="special">);</span> <span class="comment">// __lt__
</span></pre>
<p> <p>
The code snippet above is very clear and needs almost no explanation at The code snippet above is very clear and needs almost no explanation at all.
all. It is virtually the same as the operators' signatures. Just take It is virtually the same as the operators' signatures. Just take note that
note that <tt class="literal">self</tt> refers to FilePos object. Also, not every class <tt class="literal">T</tt> that <tt class="literal">self</tt> refers to FilePos object. Also, not every class
you might need to interact with in an operator expression is (cheaply) <tt class="literal">T</tt> that you might need to interact with in an operator
default-constructible. You can use <tt class="literal">other&lt;T&gt;()</tt> in place of an actual expression is (cheaply) default-constructible. You can use <tt class="literal">other&lt;T&gt;()</tt>
<tt class="literal">T</tt> instance when writing "self expressions".</p> in place of an actual <tt class="literal">T</tt> instance when writing "self
expressions".
</p>
<a name="class_operators_special_functions.special_methods"></a><h2> <a name="class_operators_special_functions.special_methods"></a><h2>
<a name="id448230"></a>Special Methods</h2> <a name="id448698"></a>
Special Methods
</h2>
<p> <p>
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python supports all of the Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
standard special method names supported by real Python class instances. A supports all of the standard special method names supported by real Python
similar set of intuitive interfaces can also be used to wrap C++ functions class instances. A similar set of intuitive interfaces can also be used to
that correspond to these Python <span class="emphasis"><em>special functions</em></span>. Example:</p> wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>.
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> Rational</span><span class="special"> Example:
{</span><span class="keyword"> public</span><span class="special">:</span><span class="keyword"> operator</span><span class="keyword"> double</span><span class="special">()</span><span class="keyword"> const</span><span class="special">;</span><span class="special"> };</span><span class="identifier"> </p>
<pre class="programlisting">
<span class="keyword">class</span> <span class="identifier">Rational</span>
<span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">operator</span> <span class="keyword">double</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="special">};</span>
Rational</span><span class="identifier"> pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span><span class="identifier"> Rational</span><span class="special">);</span><span class="identifier"> <span class="identifier">Rational</span> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span> <span class="identifier">Rational</span><span class="special">);</span>
Rational</span><span class="identifier"> abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier"> <span class="identifier">Rational</span> <span class="identifier">abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span>
ostream</span><span class="special">&amp;</span><span class="keyword"> operator</span><span class="special">&lt;&lt;(</span><span class="identifier">ostream</span><span class="special">&amp;,</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier"> <span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">ostream</span><span class="special">&amp;,</span><span class="identifier">Rational</span><span class="special">);</span>
class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;(</span><span class="string">"Rational"</span><span class="special">)</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;(</span><span class="string">"Rational"</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span><span class="comment"> // __float__ <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __float__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> other</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;))</span><span class="comment"> // __pow__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;))</span> <span class="comment">// __pow__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span><span class="comment"> // __abs__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __abs__
</span><span class="special"> .</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span><span class="comment"> // __str__ </span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __str__
</span><span class="special"> ;</span></tt></pre> </span> <span class="special">;</span>
</pre>
<p> <p>
Need we say more?</p> Need we say more?
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span> What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>? <span class="inlinemediaobject"><img src="../images/note.png"></span>
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">&lt;&lt;</span></tt> to do its work (i.e. What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</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">&lt;&lt;</span></tt> to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt>
<tt class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></tt> is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.</td></tr></tbody> is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.</td></tr></tbody>
</table></div> </table></div>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -32,17 +32,18 @@
<dt><span class="section"><a href="functions.html#python.auto_overloading">Auto-Overloading</a></span></dt> <dt><span class="section"><a href="functions.html#python.auto_overloading">Auto-Overloading</a></span></dt>
</dl></div> </dl></div>
<p> <p>
In this chapter, we'll look at Boost.Python powered functions in closer FunctionsIn this chapter, we'll look at Boost.Python powered functions in closer
detail. We shall see some facilities to make exposing C++ functions to detail. We shall see some facilities to make exposing C++ functions to Python
Python safe from potential pifalls such as dangling pointers and safe from potential pifalls such as dangling pointers and references. We shall
references. We shall also see facilities that will make it even easier for also see facilities that will make it even easier for us to expose C++ functions
us to expose C++ functions that take advantage of C++ features such as that take advantage of C++ features such as overloading and default arguments.
overloading and default arguments.</p> </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><span class="emphasis"><em>Read on...</em></span></p></blockquote></div>
<p> <p>
But before you do, you might want to fire up Python 2.2 or later and type But before you do, you might want to fire up Python 2.2 or later and type
<tt class="literal">&gt;&gt;&gt; import this</tt>.</p> <tt class="literal">&gt;&gt;&gt; import this</tt>.
<pre class="programlisting"><tt class="literal">&gt;&gt;&gt; import this </p>
<pre class="programlisting">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters The Zen of Python, by Tim Peters
Beautiful is better than ugly. Beautiful is better than ugly.
Explicit is better than implicit. Explicit is better than implicit.
@@ -63,187 +64,231 @@ Although never is often better than <span class="bold"><b>right</b></span> now.
If the implementation is hard to explain, it's a bad idea. 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. 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! Namespaces are one honking great idea -- let's do more of those!
</tt></pre> </pre>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.call_policies"></a>Call Policies</h3></div></div></div> <a name="python.call_policies"></a>Call Policies</h3></div></div></div>
<p> <p>
In C++, we often deal with arguments and return types such as pointers Call PoliciesIn C++, we often deal with arguments and return types such as
and references. Such primitive types are rather, ummmm, low level and pointers and references. Such primitive types are rather, ummmm, low level
they really don't tell us much. At the very least, we don't know the and they really don't tell us much. At the very least, we don't know the
owner of the pointer or the referenced object. No wonder languages owner of the pointer or the referenced object. No wonder languages such as
such as Java and Python never deal with such low level entities. In Java and Python never deal with such low level entities. In C++, it's usually
C++, it's usually considered a good practice to use smart pointers considered a good practice to use smart pointers which exactly describe ownership
which exactly describe ownership semantics. Still, even good C++ semantics. Still, even good C++ interfaces use raw references and pointers
interfaces use raw references and pointers sometimes, so Boost.Python sometimes, so Boost.Python must deal with them. To do this, it may need your
must deal with them. To do this, it may need your help. Consider the help. Consider the following C++ function:
following C++ function:</p> </p>
<pre class="programlisting"><tt class="literal"><span class="identifier">X</span><span class="special">&amp;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">);</span></tt></pre> <pre class="programlisting">
<span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span>
</pre>
<p> <p>
How should the library wrap this function? A naive approach builds a How should the library wrap this function? A naive approach builds a Python
Python X object around result reference. This strategy might or might X object around result reference. This strategy might or might not work out.
not work out. Here's an example where it didn't</p> Here's an example where it didn't
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span><span class="identifier"> z</span><span class="special">)</span> #<span class="identifier"> x</span><span class="identifier"> refers</span><span class="identifier"> to</span><span class="identifier"> some</span><span class="identifier"> C</span><span class="special">++</span><span class="identifier"> X</span><span class="special"> </p>
&gt;&gt;&gt;</span><span class="identifier"> del</span><span class="identifier"> y</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> #<span class="identifier"> CRASH</span><span class="special">!</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">y</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
</pre>
<p> <p>
What's the problem?</p> What's the problem?
</p>
<p> <p>
Well, what if f() was implemented as shown below:</p> Well, what if f() was implemented as shown below:
<pre class="programlisting"><tt class="literal"><span class="identifier">X</span><span class="special">&amp;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">)</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
y</span><span class="special">.</span><span class="identifier">z</span><span class="special"> =</span><span class="identifier"> z</span><span class="special">;</span><span class="keyword"> <span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
return</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span><span class="special"> <span class="special">{</span>
}</span></tt></pre> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p> <p>
The problem is that the lifetime of result X&amp; is tied to the lifetime The problem is that the lifetime of result X&amp; is tied to the lifetime
of y, because the f() returns a reference to a member of the y of y, because the f() returns a reference to a member of the y object. This
object. This idiom is is not uncommon and perfectly acceptable in the idiom is is not uncommon and perfectly acceptable in the context of C++.
context of C++. However, Python users should not be able to crash the However, Python users should not be able to crash the system just by using
system just by using our C++ interface. In this case deleting y will our C++ interface. In this case deleting y will invalidate the reference
invalidate the reference to X. We have a dangling reference.</p> to X. We have a dangling reference.
</p>
<p> <p>
Here's what's happening:</p> Here's what's happening:
</p>
<div class="orderedlist"><ol type="1"> <div class="orderedlist"><ol type="1">
<li> <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> <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>
</li> </li>
<li> <li>
A reference to <tt class="literal">y.x</tt> is returned A reference to <tt class="literal">y.x</tt> is returned
</li> </li>
<li> <li>
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference <tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
</li> </li>
<li> <li>
<tt class="literal">x.some_method()</tt> is called <tt class="literal">x.some_method()</tt> is called
</li> </li>
<li><span class="bold"><b>BOOM!</b></span></li> <li><span class="bold"><b>BOOM!</b></span></li>
</ol></div> </ol></div>
<p> <p>
We could copy result into a new object:</p> We could copy result into a new object:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span><span class="identifier"> z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span><span class="comment"> # Result disappears <pre class="programlisting">
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span><span class="comment"> # No crash, but still bad <span class="special">&gt;&gt;&gt;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span> <span class="comment"># Result disappears
</span><span class="number">3.14</span></tt></pre> </span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="comment"># No crash, but still bad
</span><span class="number">3.14</span>
</pre>
<p> <p>
This is not really our intent of our C++ interface. We've broken our This is not really our intent of our C++ interface. We've broken our promise
promise that the Python interface should reflect the C++ interface as that the Python interface should reflect the C++ interface as closely as
closely as possible.</p> possible.
</p>
<p> <p>
Our problems do not end there. Suppose Y is implemented as follows:</p> Our problems do not end there. Suppose Y is implemented as follows:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> Y</span><span class="special"> <pre class="programlisting">
{</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">Y</span>
X</span><span class="identifier"> x</span><span class="special">;</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">;</span><span class="keyword"> <span class="special">{</span>
int</span><span class="identifier"> z_value</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> return</span><span class="identifier"> z</span><span class="special">-&gt;</span><span class="identifier">value</span><span class="special">();</span><span class="special"> }</span><span class="special"> <span class="identifier">X</span> <span class="identifier">x</span><span class="special">;</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">;</span>
};</span></tt></pre> <span class="keyword">int</span> <span class="identifier">z_value</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">z</span><span class="special">-&gt;</span><span class="identifier">value</span><span class="special">();</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<p> <p>
Notice that the data member <tt class="literal">z</tt> is held by class Y using a raw Notice that the data member <tt class="literal">z</tt> is held by class Y using
pointer. Now we have a potential dangling pointer problem inside Y:</p> a raw pointer. Now we have a potential dangling pointer problem inside Y:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> x</span><span class="special"> =</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span><span class="identifier"> z</span><span class="special">)</span> #<span class="identifier"> y</span><span class="identifier"> refers</span><span class="identifier"> to</span><span class="identifier"> z</span><span class="special"> </p>
&gt;&gt;&gt;</span><span class="identifier"> del</span><span class="identifier"> z</span>       #<span class="identifier"> Kill</span><span class="identifier"> the</span><span class="identifier"> z</span><span class="identifier"> object</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> #<span class="identifier"> CRASH</span><span class="special">!</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">del</span> <span class="identifier">z</span> # <span class="identifier">Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
</pre>
<p> <p>
For reference, here's the implementation of <tt class="literal">f</tt> again:</p> For reference, here's the implementation of <tt class="literal">f</tt> again:
<pre class="programlisting"><tt class="literal"><span class="identifier">X</span><span class="special">&amp;</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">)</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
y</span><span class="special">.</span><span class="identifier">z</span><span class="special"> =</span><span class="identifier"> z</span><span class="special">;</span><span class="keyword"> <span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&amp;</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
return</span><span class="identifier"> y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span><span class="special"> <span class="special">{</span>
}</span></tt></pre> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p> <p>
Here's what's happening:</p> Here's what's happening:
</p>
<div class="orderedlist"><ol type="1"> <div class="orderedlist"><ol type="1">
<li> <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> <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>
</li> </li>
<li> <li>
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt> A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
</li> </li>
<li> <li>
A reference to <tt class="literal">y.x</tt> is returned A reference to <tt class="literal">y.x</tt> is returned
</li> </li>
<li> <li>
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer <tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
</li> </li>
<li> <li>
<tt class="literal">y.z_value()</tt> is called <tt class="literal">y.z_value()</tt> is called
</li> </li>
<li> <li>
<tt class="literal">z-&gt;value()</tt> is called <tt class="literal">z-&gt;value()</tt> is called
</li> </li>
<li><span class="bold"><b>BOOM!</b></span></li> <li><span class="bold"><b>BOOM!</b></span></li>
</ol></div> </ol></div>
<a name="call_policies.call_policies"></a><h2> <a name="call_policies.call_policies"></a><h2>
<a name="id449896"></a>Call Policies</h2> <a name="id450599"></a>
Call Policies
</h2>
<p> <p>
Call Policies may be used in situations such as the example detailed above. 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, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
are our friends:</p> are our friends:
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> f</span><span class="special">,</span><span class="identifier"> </p>
return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span><span class="identifier"> <pre class="programlisting">
with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span><span class="number"> 2</span><span class="special">&gt;</span><span class="special"> &gt;());</span></tt></pre> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span>
<span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span>
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
</pre>
<p> <p>
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you ask?</p> What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
<pre class="programlisting"><tt class="literal"><span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span></tt></pre> ask?
</p>
<pre class="programlisting">
<span class="identifier">return_internal_reference</span><span class="special">&lt;</span><span class="number">1</span>
</pre>
<p> <p>
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&amp; y</tt>, is the Informs Boost.Python that the first argument, in our case <tt class="literal">Y&amp;
owner of the returned reference: <tt class="literal">X&amp;</tt>. The "<tt class="literal">1</tt>" simply specifies the y</tt>, is the owner of the returned reference: <tt class="literal">X&amp;</tt>.
first argument. In short: "return an internal reference <tt class="literal">X&amp;</tt> owned by the The "<tt class="literal">1</tt>" simply specifies the first argument.
1st argument <tt class="literal">Y&amp; y</tt>".</p> In short: "return an internal reference <tt class="literal">X&amp;</tt> owned
<pre class="programlisting"><tt class="literal"><span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span><span class="number"> 2</span><span class="special">&gt;</span></tt></pre> by the 1st argument <tt class="literal">Y&amp; y</tt>".
</p>
<pre class="programlisting">
<span class="identifier">with_custodian_and_ward</span><span class="special">&lt;</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>
</pre>
<p> <p>
Informs Boost.Python that the lifetime of the argument indicated by ward 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 (i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&amp; y</tt>).</p> of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&amp;
y</tt>).
</p>
<p> <p>
It is also important to note that we have defined two policies above. Two It is also important to note that we have defined two policies above. Two
or more policies can be composed by chaining. Here's the general syntax:</p> or more policies can be composed by chaining. Here's the general syntax:
<pre class="programlisting"><tt class="literal"><span class="identifier">policy1</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier"> </p>
policy2</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier"> <pre class="programlisting">
policy3</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...&gt;</span><span class="special"> &gt;</span><span class="special"> &gt;</span></tt></pre> <span class="identifier">policy1</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy2</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...,</span>
<span class="identifier">policy3</span><span class="special">&lt;</span><span class="identifier">args</span><span class="special">...&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
</pre>
<p> <p>
Here is the list of predefined call policies. A complete reference detailing Here is the list of predefined call policies. A complete reference detailing
these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.</p> these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
<span class="bold"><b>with_custodian_and_ward</b></span><br> <span class="bold"><b>with_custodian_and_ward</b></span><br> Ties lifetimes
Ties lifetimes of the arguments of the arguments
</li> </li>
<li> <li>
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br> <span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
Ties lifetimes of the arguments and results Ties lifetimes of the arguments and results
</li> </li>
<li> <li>
<span class="bold"><b>return_internal_reference</b></span><br> <span class="bold"><b>return_internal_reference</b></span><br> Ties lifetime
Ties lifetime of one argument to that of result of one argument to that of result
</li> </li>
<li> <li>
<span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><br> <span class="bold"><b>return_value_policy&lt;T&gt; with T one of:</b></span><br>
</li> </li>
<li> <li>
<span class="bold"><b>reference_existing_object</b></span><br> <span class="bold"><b>reference_existing_object</b></span><br> naive
naive (dangerous) approach (dangerous) approach
</li> </li>
<li> <li>
<span class="bold"><b>copy_const_reference</b></span><br> <span class="bold"><b>copy_const_reference</b></span><br> Boost.Python
Boost.Python v1 approach v1 approach
</li> </li>
<li> <li>
<span class="bold"><b>copy_non_const_reference</b></span><br> <span class="bold"><b>copy_non_const_reference</b></span><br>
</li> </li>
<li> <li>
<span class="bold"><b>manage_new_object</b></span><br> <span class="bold"><b>manage_new_object</b></span><br> Adopt a pointer
Adopt a pointer and hold the instance and hold the instance
</li> </li>
</ul></div> </ul></div>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/smiley.png"></span><span class="bold"><b>Remember the Zen, Luke:</b></span><br><br> <span class="inlinemediaobject"><img src="../images/smiley.png"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span><br><br> "Explicit
is better than implicit"<br> "In the face of ambiguity,
"Explicit is better than implicit"<br> refuse the temptation to guess"<br>
"In the face of ambiguity, refuse the temptation to guess"<br>
</td></tr></tbody> </td></tr></tbody>
</table></div> </table></div>
</div> </div>
@@ -251,226 +296,303 @@ Boost.Python v1 approach
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.overloading"></a>Overloading</h3></div></div></div> <a name="python.overloading"></a>Overloading</h3></div></div></div>
<p> <p>
The following illustrates a scheme for manually wrapping an overloaded OverloadingThe following illustrates a scheme for manually wrapping an overloaded
member functions. Of course, the same technique can be applied to wrapping member functions. Of course, the same technique can be applied to wrapping
overloaded non-member functions.</p> overloaded non-member functions.
</p>
<p> <p>
We have here our C++ class:</p> We have here our C++ class:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> X</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
bool</span><span class="identifier"> f</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">)</span><span class="special"> <span class="keyword">struct</span> <span class="identifier">X</span>
{</span><span class="keyword"> <span class="special">{</span>
return</span><span class="keyword"> true</span><span class="special">;</span><span class="special"> <span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">)</span>
}</span><span class="keyword"> <span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
<span class="special">}</span>
bool</span><span class="identifier"> f</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> b</span><span class="special">)</span><span class="special"> <span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">)</span>
{</span><span class="keyword"> <span class="special">{</span>
return</span><span class="keyword"> true</span><span class="special">;</span><span class="special"> <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
}</span><span class="keyword"> <span class="special">}</span>
bool</span><span class="identifier"> f</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> b</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> c</span><span class="special">)</span><span class="special"> <span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
{</span><span class="keyword"> <span class="special">{</span>
return</span><span class="keyword"> true</span><span class="special">;</span><span class="special"> <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
}</span><span class="keyword"> <span class="special">}</span>
int</span><span class="identifier"> f</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> b</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> c</span><span class="special">)</span><span class="special"> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">c</span><span class="special">)</span>
{</span><span class="keyword"> <span class="special">{</span>
return</span><span class="identifier"> a</span><span class="special"> +</span><span class="identifier"> b</span><span class="special"> +</span><span class="identifier"> c</span><span class="special">;</span><span class="special"> <span class="keyword">return</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
};</span><span class="special"> <span class="special">};</span>
};</span></tt></pre> <span class="special">};</span>
</pre>
<p> <p>
Class X has 4 overloaded functions. We shall start by introducing some Class X has 4 overloaded functions. We shall start by introducing some member
member function pointer variables:</p> function pointer variables:
<pre class="programlisting"><tt class="literal"><span class="keyword">bool</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span><span class="special"> =</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span><span class="keyword"> </p>
bool</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</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="special"> =</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span><span class="keyword"> <pre class="programlisting">
bool</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</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="special">)=</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span><span class="keyword"> <span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
int</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword"> int</span><span class="special">,</span><span class="keyword"> int</span><span class="special">)</span><span class="special"> =</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span></tt></pre> <span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</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="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</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="special">)=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
</pre>
<p> <p>
With these in hand, we can proceed to define and wrap this for Python:</p> With these in hand, we can proceed to define and wrap this for Python:
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx1</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx2</span><span class="special">)</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx3</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx4</span><span class="special">)</span></tt></pre> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx3</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx4</span><span class="special">)</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div> <a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
<p> <p>
Boost.Python wraps (member) function pointers. Unfortunately, C++ function Default ArgumentsBoost.Python wraps (member) function pointers. Unfortunately,
pointers carry no default argument info. Take a function <tt class="literal">f</tt> with default C++ function pointers carry no default argument info. Take a function <tt class="literal">f</tt>
arguments:</p> with default arguments:
<pre class="programlisting"><tt class="literal"><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></tt></pre> </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> <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 <tt class="literal">f</tt> has no information
about its default arguments:</p> about its default arguments:
<pre class="programlisting"><tt class="literal"><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! </p>
</span></tt></pre> <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> <p>
When we pass this function pointer to the <tt class="literal">def</tt> function, there is no way When we pass this function pointer to the <tt class="literal">def</tt> function,
to retrieve the default arguments:</p> there is no way to retrieve the default arguments:
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> f</span><span class="special">);</span><span class="comment"> // defaults lost! </p>
</span></tt></pre> <pre class="programlisting">
<span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// defaults lost!
</span></pre>
<p> <p>
Because of this, when wrapping C++ code, we had to resort to manual Because of this, when wrapping C++ code, we had to resort to manual wrapping
wrapping as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>, or as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>,
writing thin wrappers:</p> or writing thin wrappers:
<pre class="programlisting"><tt class="literal"><span class="comment">// write "thin wrappers" </p>
</span><span class="keyword">int</span><span class="identifier"> f1</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> x</span><span class="special">)</span><span class="special"> {</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span><span class="special"> }</span><span class="keyword"> <pre class="programlisting">
int</span><span class="identifier"> f2</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> x</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> y</span><span class="special">)</span><span class="special"> {</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span><span class="special"> }</span><span class="comment"> <span class="comment">// write "thin wrappers"
</span><span class="keyword">int</span> <span class="identifier">f1</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">f2</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span> <span class="special">}</span>
/*...*/ <span class="comment">/*...*/</span>
// in module init <span class="comment">// in module init
</span><span class="identifier"> def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> f</span><span class="special">);</span><span class="comment"> // all arguments </span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// all arguments
</span><span class="identifier"> def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> f2</span><span class="special">);</span><span class="comment"> // two arguments </span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">);</span> <span class="comment">// two arguments
</span><span class="identifier"> def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> f1</span><span class="special">);</span><span class="comment"> // one argument </span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f1</span><span class="special">);</span> <span class="comment">// one argument
</span></tt></pre> </span></pre>
<p> <p>
When you want to wrap functions (or member functions) that either:</p> When you want to wrap functions (or member functions) that either:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
have default arguments, or have default arguments, or
</li> </li>
<li> <li>
are overloaded with a common sequence of initial arguments are overloaded with a common sequence of initial arguments
</li> </li>
</ul></div> </ul></div>
<a name="default_arguments.boost_python_function_overloads"></a><h2> <a name="default_arguments.boost_python_function_overloads"></a><h2>
<a name="id451716"></a>BOOST_PYTHON_FUNCTION_OVERLOADS</h2> <a name="id452559"></a>
BOOST_PYTHON_FUNCTION_OVERLOADS
</h2>
<p> <p>
Boost.Python now has a way to make it easier. For instance, given a function:</p> Boost.Python now has a way to make it easier. For instance, given a function:
<pre class="programlisting"><tt class="literal"><span class="keyword">int</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> b</span><span class="special"> =</span><span class="number"> 1</span><span class="special">,</span><span class="keyword"> unsigned</span><span class="identifier"> c</span><span class="special"> =</span><span class="number"> 2</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> d</span><span class="special"> =</span><span class="number"> 3</span><span class="special">)</span><span class="special"> </p>
{</span><span class="comment"> <pre class="programlisting">
/*...*/</span><span class="special"> <span class="keyword">int</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">c</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">3</span><span class="special">)</span>
}</span></tt></pre> <span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
</pre>
<p> <p>
The macro invocation:</p> The macro invocation:
<pre class="programlisting"><tt class="literal"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="number"> 1</span><span class="special">,</span><span class="number"> 4</span><span class="special">)</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre>
<p> <p>
will automatically create the thin wrappers for us. This macro will create 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>. The third a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
and fourth macro argument are the minimum arguments and maximum arguments, The third and fourth macro argument are the minimum arguments and maximum
respectively. In our <tt class="literal">foo</tt> function the minimum number of arguments is 1 arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt> function will number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
automatically add all the foo variants for us:</p> function will automatically add all the foo variants for us:
<pre class="programlisting"><tt class="literal"><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="identifier"> foo_overloads</span><span class="special">());</span></tt></pre> </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="default_arguments.boost_python_member_function_overloads"></a><h2>
<a name="id451995"></a>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2> <a name="id452863"></a>
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
</h2>
<p> <p>
Objects here, objects there, objects here there everywhere. More frequently Objects here, objects there, objects here there everywhere. More frequently
than anything else, we need to expose member functions of our classes to than anything else, we need to expose member functions of our classes to
Python. Then again, we have the same inconveniences as before when default Python. Then again, we have the same inconveniences as before when default
arguments or overloads with a common sequence of initial arguments come arguments or overloads with a common sequence of initial arguments come into
into play. Another macro is provided to make this a breeze.</p> play. Another macro is provided to make this a breeze.
</p>
<p> <p>
Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
<tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> may be used to automatically create may be used to automatically create the thin wrappers for wrapping member
the thin wrappers for wrapping member functions. Let's have an example:</p> functions. Let's have an example:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> george</span><span class="special"> </p>
{</span><span class="keyword"> <pre class="programlisting">
void</span><span class="identifier"> <span class="keyword">struct</span> <span class="identifier">george</span>
wack_em</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> b</span><span class="special"> =</span><span class="number"> 0</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> c</span><span class="special"> =</span><span class="char"> 'x'</span><span class="special">)</span><span class="special"> <span class="special">{</span>
{</span><span class="comment"> <span class="keyword">void</span>
/*...*/</span><span class="special"> <span class="identifier">wack_em</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">=</span> <span class="char">'x'</span><span class="special">)</span>
}</span><span class="special"> <span class="special">{</span>
};</span></tt></pre> <span class="comment">/*...*/</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p> <p>
The macro invocation:</p> The macro invocation:
<pre class="programlisting"><tt class="literal"><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></tt></pre> </p>
<pre class="programlisting">
<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> <p>
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt> member function will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
fourth macro argument). The thin wrappers are all enclosed in a class named the third and fourth macro argument). The thin wrappers are all enclosed
<tt class="literal">george_overloads</tt> that can then be used as an argument to <tt class="literal">def(...)</tt>:</p> in a class named <tt class="literal">george_overloads</tt> that can then be used
<pre class="programlisting"><tt class="literal"><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"> &amp;</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></tt></pre> as an argument to <tt class="literal">def(...)</tt>:
</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">&amp;</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>
</pre>
<p> <p>
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads reference</a> See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
for details.</p> reference</a> for details.
</p>
<a name="default_arguments.init_and_optional"></a><h2> <a name="default_arguments.init_and_optional"></a><h2>
<a name="id452323"></a>init and optional</h2> <a name="id453212"></a>
init and optional
</h2>
<p> <p>
A similar facility is provided for class constructors, again, with A similar facility is provided for class constructors, again, with default
default arguments or a sequence of overloads. Remember <tt class="literal">init&lt;...&gt;</tt>? For example, arguments or a sequence of overloads. Remember <tt class="literal">init&lt;...&gt;</tt>?
given a class X with a constructor:</p> For example, given a class X with a constructor:
<pre class="programlisting"><tt class="literal"><span class="keyword">struct</span><span class="identifier"> X</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
X</span><span class="special">(</span><span class="keyword">int</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> b</span><span class="special"> =</span><span class="char"> 'D'</span><span class="special">,</span><span class="identifier"> std</span><span class="special">::</span><span class="identifier">string</span><span class="identifier"> c</span><span class="special"> =</span><span class="string"> "constructor"</span><span class="special">,</span><span class="keyword"> double</span><span class="identifier"> d</span><span class="special"> =</span><span class="number"> 0.0</span><span class="special">);</span><span class="comment"> <span class="keyword">struct</span> <span class="identifier">X</span>
/*...*/</span><span class="special"> <span class="special">{</span>
}</span></tt></pre> <span class="identifier">X</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="char">'D'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">c</span> <span class="special">=</span> <span class="string">"constructor"</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">0.0</span><span class="special">);</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
</pre>
<p> <p>
You can easily add this constructor to Boost.Python in one shot:</p> You can easily add this constructor to Boost.Python in one shot:
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="identifier"> optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span><span class="identifier"> std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span><span class="keyword"> double</span><span class="special">&gt;</span><span class="special"> &gt;())</span></tt></pre> </p>
<pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p> <p>
Notice the use of <tt class="literal">init&lt;...&gt;</tt> and <tt class="literal">optional&lt;...&gt;</tt> to signify the default Notice the use of <tt class="literal">init&lt;...&gt;</tt> and <tt class="literal">optional&lt;...&gt;</tt>
(optional arguments).</p> to signify the default (optional arguments).
</p>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div> <a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
<p> <p>
It was mentioned in passing in the previous section that Auto-OverloadingIt 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> <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
can also be used for overloaded functions and member functions with a can also be used for overloaded functions and member functions with a common
common sequence of initial arguments. Here is an example:</p> sequence of initial arguments. Here is an example:
<pre class="programlisting"><tt class="literal"><span class="keyword">void</span><span class="identifier"> foo</span><span class="special">()</span><span class="special"> </p>
{</span><span class="comment"> <pre class="programlisting">
/*...*/</span><span class="special"> <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
}</span><span class="keyword"> <span class="special">{</span>
<span class="comment">/*...*/</span>
<span class="special">}</span>
void</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">bool</span><span class="identifier"> a</span><span class="special">)</span><span class="special"> <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
/*...*/</span><span class="special"> <span class="comment">/*...*/</span>
}</span><span class="keyword"> <span class="special">}</span>
void</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">bool</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> b</span><span class="special">)</span><span class="special"> <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
/*...*/</span><span class="special"> <span class="comment">/*...*/</span>
}</span><span class="keyword"> <span class="special">}</span>
void</span><span class="identifier"> foo</span><span class="special">(</span><span class="keyword">bool</span><span class="identifier"> a</span><span class="special">,</span><span class="keyword"> int</span><span class="identifier"> b</span><span class="special">,</span><span class="keyword"> char</span><span class="identifier"> c</span><span class="special">)</span><span class="special"> <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
/*...*/</span><span class="special"> <span class="comment">/*...*/</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
Like in the previous section, we can generate thin wrappers for these Like in the previous section, we can generate thin wrappers for these overloaded
overloaded functions in one-shot:</p> functions in one-shot:
<pre class="programlisting"><tt class="literal"><span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="number"> 0</span><span class="special">,</span><span class="number"> 3</span><span class="special">)</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
</pre>
<p> <p>
Then...</p> Then...
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span><span class="identifier"> foo</span><span class="special">,</span><span class="identifier"> foo_overloads</span><span class="special">());</span></tt></pre> </p>
<pre class="programlisting">
<span class="special">.</span><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>
<p> <p>
Notice though that we have a situation now where we have a minimum of zero Notice though that we have a situation now where we have a minimum of zero
(0) arguments and a maximum of 3 arguments.</p> (0) arguments and a maximum of 3 arguments.
</p>
<a name="auto_overloading.manual_wrapping"></a><h2> <a name="auto_overloading.manual_wrapping"></a><h2>
<a name="id452969"></a>Manual Wrapping</h2> <a name="id453917"></a>
Manual Wrapping
</h2>
<p> <p>
It is important to emphasize however that <span class="bold"><b>the overloaded functions must It is important to emphasize however that <span class="bold"><b>the overloaded
have a common sequence of initial arguments</b></span>. Otherwise, our scheme above functions must have a common sequence of initial arguments</b></span>. Otherwise,
will not work. If this is not the case, we have to wrap our functions our scheme above will not work. If this is not the case, we have to wrap
<a href="functions.html#python.overloading" title="Overloading">manually</a>.</p> our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
</p>
<p> <p>
Actually, we can mix and match manual wrapping of overloaded functions and 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 automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following up on our example and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
presented in the section <a href="functions.html#python.overloading" title="Overloading">on overloading</a>, since the up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
first 4 overload functins have a common sequence of initial arguments, we overloading</a>, since the first 4 overload functins have a common sequence
can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> to automatically wrap the of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
first three of the <tt class="literal">def</tt>s and manually wrap just the last. Here's to automatically wrap the first three of the <tt class="literal">def</tt>s and
how we'll do this:</p> manually wrap just the last. Here's how we'll do this:
<pre class="programlisting"><tt class="literal"><span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span><span class="identifier"> f</span><span class="special">,</span><span class="number"> 1</span><span class="special">,</span><span class="number"> 4</span><span class="special">)</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
</pre>
<p> <p>
Create a member function pointers as above for both X::f overloads:</p> Create a member function pointers as above for both X::f overloads:
<pre class="programlisting"><tt class="literal"><span class="keyword">bool</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</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="special">)</span><span class="special"> =</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span><span class="keyword"> </p>
int</span><span class="special"> (</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword"> int</span><span class="special">,</span><span class="keyword"> int</span><span class="special">)</span><span class="special"> =</span><span class="special"> &amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span></tt></pre> <pre class="programlisting">
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</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="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
</pre>
<p> <p>
Then...</p> Then...
<pre class="programlisting"><tt class="literal"><span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx1</span><span class="special">,</span><span class="identifier"> xf_overloads</span><span class="special">());</span><span class="special"> </p>
.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span><span class="identifier"> fx2</span><span class="special">)</span></tt></pre> <pre class="programlisting">
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">,</span> <span class="identifier">xf_overloads</span><span class="special">());</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
</pre>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -25,79 +25,88 @@
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <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="python.hello"></a> Building Hello World</h2></div></div></div>
<a name="hello.from_start_to_finish"></a><h2> <a name="hello._building_hello_worldfrom_start_to_finish"></a><h2>
<a name="id374047"></a>From Start To Finish</h2> <a name="id442456"></a>
Building Hello WorldFrom Start To Finish
</h2>
<p> <p>
Now the first thing you'd want to do is to build the Hello World module and 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 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 necessary to achieve that. We shall use the build tool that comes bundled with
with every boost distribution: <span class="bold"><b>bjam</b></span>.</p> every boost distribution: <span class="bold"><b>bjam</b></span>.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>Building without bjam</b></span><br><br> <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Building without bjam</b></span><br><br> Besides bjam,
there are of course other ways to get your module built. What's written
Besides bjam, there are of course other ways to get your module built. here should not be taken as "the one and only way". There are
What's written here should not be taken as "the one and only way". of course other build tools apart from <tt class="literal">bjam</tt>.<br><br> Take note however that the preferred build tool for Boost.Python
There are of course other build tools apart from <tt class="literal">bjam</tt>.<br><br> 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
Take note however that the preferred build tool for Boost.Python is bjam. come from people who had to use a different tool. </td></tr></tbody>
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the "I can't build Boost.Python" problems come from people
who had to use a different tool.
</td></tr></tbody>
</table></div> </table></div>
<p> <p>
We shall skip over the details. Our objective will be to simply create the 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 hello world module and run it in Python. For a complete reference to building
building Boost.Python, check out: <a href="../../../../building.html" target="_top">building.html</a>. Boost.Python, check out: <a href="../../../../building.html" target="_top">building.html</a>.
After this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built two DLLs:</p> After this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built two
DLLs:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
boost_python.dll boost_python.dll
</li> </li>
<li> <li>
hello.pyd hello.pyd
</li> </li>
</ul></div> </ul></div>
<p> <p>
if you are on Windows, and</p> if you are on Windows, and
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
libboost_python.so libboost_python.so
</li> </li>
<li> <li>
hello.so hello.so
</li> </li>
</ul></div> </ul></div>
<p> <p>
if you are on Unix.</p> if you are on Unix.
</p>
<p> <p>
The tutorial example can be found in the directory: The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
<tt class="literal">libs/python/example/tutorial</tt>. There, you can find:</p> There, you can find:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
hello.cpp hello.cpp
</li> </li>
<li> <li>
Jamfile Jamfile
</li> </li>
</ul></div> </ul></div>
<p> <p>
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The <tt class="literal">Jamfile</tt> is a The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
minimalist <span class="emphasis"><em>bjam</em></span> script that builds the DLLs for us.</p> <tt class="literal">Jamfile</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
that builds the DLLs for us.
</p>
<p> <p>
Before anything else, you should have the bjam executable in your boost Before anything else, you should have the bjam executable in your boost directory
directory or somewhere in your path such that <tt class="literal">bjam</tt> can be executed in or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
the command line. Pre-built Boost.Jam executables are available for most in the command line. Pre-built Boost.Jam executables are available for most
platforms. The complete list of Bjam executables can be found 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>.
<a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.</p> </p>
<a name="hello.let_s_jam_"></a><h2> <a name="hello.let_s_jam_"></a><h2>
<a name="id372653"></a>Let's Jam!</h2> <a name="id373799"></a>
Let's Jam!
</h2>
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p> <p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
<p> <p>
Here is our minimalist Jamfile:</p> Here is our minimalist Jamfile:
<pre class="programlisting"><tt class="literal"># This is the top of our own project tree </p>
<pre class="programlisting"># This is the top of our own project tree
project-root ; project-root ;
import python ; import python ;
@@ -107,85 +116,106 @@ extension hello # Declare a Python extension called hello
# requirements and dependencies for Boost.Python extensions # requirements and dependencies for Boost.Python extensions
&lt;template&gt;@boost/libs/python/build/extension &lt;template&gt;@boost/libs/python/build/extension
; ;
</tt></pre> </pre>
<p> <p>
First, we need to specify our location. You may place your project anywhere. First, we need to specify our location. You may place your project anywhere.
<tt class="literal">project-root</tt> allows you to do that.</p> <tt class="literal">project-root</tt> allows you to do that.
<pre class="programlisting"><tt class="literal">project-root ; </p>
</tt></pre> <pre class="programlisting">project-root ;
</pre>
<p> <p>
By doing so, you'll need a Jamrules file. Simply copy the one in the 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>
<a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a> and tweak and tweak the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost
the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost root directory is. The file root directory is. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you can follow.</p> instructions</a> you can follow.
</p>
<p> <p>
Then we will import the definitions needed by Python modules:</p> Then we will import the definitions needed by Python modules:
<pre class="programlisting"><tt class="literal">import python ; </p>
</tt></pre> <pre class="programlisting">import python ;
</pre>
<p> <p>
Finally we declare our <tt class="literal">hello</tt> extension:</p> Finally we declare our <tt class="literal">hello</tt> extension:
<pre class="programlisting"><tt class="literal">extension hello # Declare a Python extension called hello </p>
<pre class="programlisting">extension hello # Declare a Python extension called hello
: hello.cpp # source : hello.cpp # source
# requirements and dependencies for Boost.Python extensions # requirements and dependencies for Boost.Python extensions
&lt;template&gt;@boost/libs/python/build/extension &lt;template&gt;@boost/libs/python/build/extension
; ;
</tt></pre> </pre>
<p> <p>
The last part tells BJam that we are depending on the Boost Python Library.</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="hello.running_bjam"></a><h2>
<a name="id372775"></a>Running bjam</h2> <a name="id373910"></a>
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line interpreter.</p> Running bjam
<div class="blockquote"><blockquote class="blockquote"><p>Start it up.</p></blockquote></div> </h2>
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
interpreter.
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
Start it up.
</p></blockquote></div>
<p> <p>
Make sure that the environment is set so that we can invoke the C++ Make sure that the environment is set so that we can invoke the C++ compiler.
compiler. With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
file. For instance:</p> file. For instance:
<pre class="programlisting"><tt class="literal">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat </p>
</tt></pre> <pre class="programlisting">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
</pre>
<p> <p>
Some environment variables will have to be setup for proper building of our Some environment variables will have to be setup for proper building of our
Python modules. Example:</p> Python modules. Example:
<pre class="programlisting"><tt class="literal">set PYTHON_ROOT=c:/dev/tools/python </p>
<pre class="programlisting">set PYTHON_ROOT=c:/dev/tools/python
set PYTHON_VERSION=2.2 set PYTHON_VERSION=2.2
</tt></pre> </pre>
<p> <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 <tt class="literal">c:/dev/tools/python</tt>
and that we are using Python version 2.2. You'll have to tweak these and that we are using Python version 2.2. You'll have to tweak these appropriately.
appropriately.</p> </p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/tip.png"></span> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span> "2.2.1", <span class="inlinemediaobject"><img src="../images/tip.png"></span>
even if that's the version you have.</td></tr></tbody> Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span>
"2.2.1", even if that's the version you have.</td></tr></tbody>
</table></div> </table></div>
<p> <p>
Take note that you may also do that through the Jamrules file we put in Take note that you may also do that through the Jamrules file we put in our
our project as detailed above. The file project as detailed above. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed instructions</a> you instructions</a> you can follow.
can follow.</p> </p>
<p> <p>
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt> 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> is situated.</p> where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamfile"</tt>
is situated.
</p>
<p> <p>
Finally:</p> Finally:
<pre class="programlisting"><tt class="literal"><span class="identifier">bjam</span><span class="special"> -</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">bjam</span> <span class="special">-</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span>
</pre>
<p> <p>
We are again assuming that we are using Microsoft Visual C++ version 7.1. If We are again assuming that we are using Microsoft Visual C++ version 7.1. If
not, then you will have to specify the appropriate tool. See not, then you will have to specify the appropriate tool. See <a href="../../../../../../../tools/build/index.html" target="_top">Building
<a href="../../../../../../../tools/build/index.html" target="_top">Building Boost Libraries</a> for Boost Libraries</a> for further details.
further details.</p> </p>
<p> <p>
It should be building now:</p> It should be building now:
<pre class="programlisting"><tt class="literal">cd C:\dev\boost\libs\python\example\tutorial </p>
<pre class="programlisting">cd C:\dev\boost\libs\python\example\tutorial
bjam -sTOOLS=msvc bjam -sTOOLS=msvc
...patience... ...patience...
...found 1703 targets... ...found 1703 targets...
...updating 40 targets... ...updating 40 targets...
</tt></pre> </pre>
<p> <p>
And so on... Finally:</p> And so on... Finally:
<pre class="programlisting"><tt class="literal">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th </p>
<pre class="programlisting">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
on.dll\vc-7_1\debug\threading-multi\boost_python.exp on.dll\vc-7_1\debug\threading-multi\boost_python.exp
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
@@ -195,45 +225,54 @@ al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
...updated 31 targets... ...updated 31 targets...
</tt></pre> </pre>
<p> <p>
If all is well, you should now have:</p> If all is well, you should now have:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
boost_python.dll boost_python.dll
</li> </li>
<li> <li>
hello.pyd hello.pyd
</li> </li>
</ul></div> </ul></div>
<p> <p>
if you are on Windows, and</p> if you are on Windows, and
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
libboost_python.so libboost_python.so
</li> </li>
<li> <li>
hello.so hello.so
</li> </li>
</ul></div> </ul></div>
<p> <p>
if you are on Unix.</p> if you are on Unix.
<p><tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be found somewhere in your project's </p>
<tt class="literal">bin</tt> directory. After a successful build, you can just link in these DLLs with <p><tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be
the Python interpreter. In Windows for example, you can simply put these libraries found somewhere in your project's <tt class="literal">bin</tt> directory. After a
inside the directory where the Python executable is.</p> successful build, you can just link in these DLLs with the Python interpreter.
In Windows for example, you can simply put these libraries inside the directory
where the Python executable is.
</p>
<p> <p>
You may now fire up Python and run our hello module:</p> You may now fire up Python and run our hello module:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span>
hello</span><span class="special">,</span><span class="identifier"> world</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
</pre>
<p></p> <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><span class="bold"><b>There you go... Have fun!</b></span></p></blockquote></div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -26,104 +26,156 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both"> <div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="python.iterators"></a>Iterators</h2></div></div></div> <a name="python.iterators"></a>Iterators</h2></div></div></div>
<p> <p>
In C++, and STL in particular, we see iterators everywhere. Python also has IteratorsIn C++, and STL in particular, we see iterators everywhere. Python
iterators, but these are two very different beasts.</p> also has iterators, but these are two very different beasts.
</p>
<p><span class="bold"><b>C++ iterators:</b></span></p> <p><span class="bold"><b>C++ iterators:</b></span></p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
C++ has 5 type categories (random-access, bidirectional, forward, input, output) C++ has 5 type categories (random-access, bidirectional, forward, input,
</li> output)
</li>
<li> <li>
There are 2 Operation categories: reposition, access There are 2 Operation categories: reposition, access
</li> </li>
<li> <li>
A pair of iterators is needed to represent a (first/last) range. A pair of iterators is needed to represent a (first/last) range.
</li> </li>
</ul></div> </ul></div>
<p><span class="bold"><b>Python Iterators:</b></span></p> <p><span class="bold"><b>Python Iterators:</b></span></p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
1 category (forward) 1 category (forward)
</li> </li>
<li> <li>
1 operation category (next()) 1 operation category (next())
</li> </li>
<li> <li>
Raises StopIteration exception at end Raises StopIteration exception at end
</li> </li>
</ul></div> </ul></div>
<p> <p>
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y in x...</b></span></tt> is as follows:</p> The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
in x...</b></span></tt> is as follows:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">iter</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span><span class="comment"> # get iterator <pre class="programlisting">
</span><span class="keyword">try</span><span class="special">:</span><span class="keyword"> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span> <span class="comment"># get iterator
while</span><span class="number"> 1</span><span class="special">:</span><span class="identifier"> </span><span class="keyword">try</span><span class="special">:</span>
y</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span><span class="comment"> # get each item <span class="keyword">while</span> <span class="number">1</span><span class="special">:</span>
</span><span class="special"> ...</span><span class="comment"> # process y <span class="identifier">y</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span> <span class="comment"># get each item
</span><span class="keyword">except</span><span class="identifier"> StopIteration</span><span class="special">:</span><span class="keyword"> pass</span><span class="comment"> # iterator exhausted </span> <span class="special">...</span> <span class="comment"># process y
</span></tt></pre> </span><span class="keyword">except</span> <span class="identifier">StopIteration</span><span class="special">:</span> <span class="keyword">pass</span> <span class="comment"># iterator exhausted
</span></pre>
<p> <p>
Boost.Python provides some mechanisms to make C++ iterators play along Boost.Python provides some mechanisms to make C++ iterators play along nicely
nicely as Python iterators. What we need to do is to produce 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
appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that is compatible is compatible with the Python iteration protocol. For example:
with the Python iteration protocol. For example:</p> </p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> get_iterator</span><span class="special"> =</span><span class="identifier"> iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span><span class="special"> &gt;();</span><span class="identifier"> <pre class="programlisting">
object</span><span class="identifier"> iter</span><span class="special"> =</span><span class="identifier"> get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span><span class="identifier"> <span class="identifier">object</span> <span class="identifier">get_iterator</span> <span class="special">=</span> <span class="identifier">iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;();</span>
object</span><span class="identifier"> first</span><span class="special"> =</span><span class="identifier"> iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span></tt></pre> <span class="identifier">object</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
<span class="identifier">object</span> <span class="identifier">first</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span>
</pre>
<p> <p>
Or for use in class_&lt;&gt;:</p> Or for use in class_&lt;&gt;:
<pre class="programlisting"><tt class="literal"><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">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span><span class="special"> &gt;())</span></tt></pre> </p>
<pre class="programlisting">
<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">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
</pre>
<p><span class="bold"><b>range</b></span></p> <p><span class="bold"><b>range</b></span></p>
<p> <p>
We can create a Python savvy iterator using the range function:</p> We can create a Python savvy iterator using the range function:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
range(start, finish) range(start, finish)
</li> </li>
<li> <li>
range&lt;Policies,Target&gt;(start, finish) range&lt;Policies,Target&gt;(start, finish)
</li> </li>
</ul></div> </ul></div>
<p> <p>
Here, start/finish may be one of:</p> Here, start/finish may be one of:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
member data pointers member data pointers
</li> </li>
<li> <li>
member function pointers member function pointers
</li> </li>
<li> <li>
adaptable function object (use Target parameter) adaptable function object (use Target parameter)
</li> </li>
</ul></div> </ul></div>
<p><span class="bold"><b>iterator</b></span></p> <p><span class="bold"><b>iterator</b></span></p>
<div class="itemizedlist"><ul type="disc"><li> <div class="itemizedlist"><ul type="disc"><li>
iterator&lt;T, Policies&gt;() iterator&lt;T, Policies&gt;()
</li></ul></div> </li></ul></div>
<p> <p>
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply calls <tt class="literal">range</tt> Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
with &amp;T::begin, &amp;T::end.</p> calls <tt class="literal">range</tt> with &amp;T::begin, &amp;T::end.
</p>
<p> <p>
Let's put this into action... Here's an example from some hypothetical Let's put this into action... Here's an example from some hypothetical bogon
bogon Particle accelerator code:</p> Particle accelerator code:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">f</span><span class="special"> =</span><span class="identifier"> Field</span><span class="special">()</span><span class="keyword"> <pre class="programlisting">
for</span><span class="identifier"> x</span><span class="keyword"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span><span class="identifier"> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">Field</span><span class="special">()</span>
smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span><span class="keyword"> <span class="keyword">for</span> <span class="identifier">x</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span>
for</span><span class="identifier"> y</span><span class="keyword"> in</span><span class="identifier"> f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span><span class="identifier"> <span class="identifier">smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span>
count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span></tt></pre> <span class="keyword">for</span> <span class="identifier">y</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span>
<span class="identifier">count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span>
</pre>
<p> <p>
Now, our C++ Wrapper:</p> Now, our C++ Wrapper:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="string">"Field"</span><span class="special">)</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"pions"</span><span class="special">,</span><span class="identifier"> range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="string">"Field"</span><span class="special">)</span>
.</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">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span></tt></pre> <span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"pions"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span>
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
</pre>
<p><span class="bold"><b>stl_input_iterator</b></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">&lt;&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
</p>
<p></p>
<pre class="programlisting">
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span>
<span class="comment">// Turn a Python sequence into an STL input range
</span> <span class="identifier">stl_input_iterator</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span>
<span class="identifier">l</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">// Part of the wrapper for list&lt;int&gt;
</span><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"list_int"</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"assign"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">list_assign</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;)</span>
<span class="comment">// ...
</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>
objects:
</p>
<p></p>
<pre class="programlisting">
<span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span>
<span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</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="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span>
</pre>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -32,234 +32,304 @@
<dt><span class="section"><a href="object.html#python.enums">Enums</a></span></dt> <dt><span class="section"><a href="object.html#python.enums">Enums</a></span></dt>
</dl></div> </dl></div>
<p> <p>
Python is dynamically typed, unlike C++ which is statically typed. Python Object InterfacePython is dynamically typed, unlike C++ which is statically
variables may hold an integer, a float, list, dict, tuple, str, long etc., typed. Python variables may hold an integer, a float, list, dict, tuple, str,
among other things. In the viewpoint of Boost.Python and C++, these 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 Pythonic variables are just instances of class <tt class="literal">object</tt>. We
this chapter how to deal with Python objects.</p> shall see in this chapter how to deal with Python objects.
</p>
<p> <p>
As mentioned, one of the goals of Boost.Python is to provide a As mentioned, one of the goals of Boost.Python is to provide a bidirectional
bidirectional mapping between C++ and Python while maintaining the Python mapping between C++ and Python while maintaining the Python feel. Boost.Python
feel. Boost.Python C++ <tt class="literal">object</tt>s are as close as possible to Python. This C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
should minimize the learning curve significantly.</p> minimize the learning curve significantly.
</p>
<p><span class="inlinemediaobject"><img src="../images/python.png"></span></p> <p><span class="inlinemediaobject"><img src="../images/python.png"></span></p>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div> <a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
<p> <p>
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the intricacies of dealing with Basic InterfaceClass <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>.
<tt class="literal">PyObject</tt>s such as managing reference counting are handled by the All the intricacies of dealing with <tt class="literal">PyObject</tt>s such as
<tt class="literal">object</tt> class. C++ object interoperability is seamless. Boost.Python C++ managing reference counting are handled by the <tt class="literal">object</tt>
<tt class="literal">object</tt>s can in fact be explicitly constructed from any C++ object.</p> class. C++ object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
can in fact be explicitly constructed from any C++ object.
</p>
<p> <p>
To illustrate, this Python code snippet:</p> To illustrate, this Python code snippet:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">def</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> y</span><span class="special">):</span><span class="keyword"> <pre class="programlisting">
if</span><span class="special"> (</span><span class="identifier">y</span><span class="special"> ==</span><span class="string"> 'foo'</span><span class="special">):</span><span class="identifier"> <span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">):</span>
x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span><span class="special"> =</span><span class="string"> 'bar'</span><span class="keyword"> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">'foo'</span><span class="special">):</span>
else</span><span class="special">:</span><span class="identifier"> <span class="identifier">x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span> <span class="special">=</span> <span class="string">'bar'</span>
x</span><span class="special">.</span><span class="identifier">items</span><span class="special"> +=</span><span class="identifier"> y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier"> x</span><span class="special">)</span><span class="keyword"> <span class="keyword">else</span><span class="special">:</span>
return</span><span class="identifier"> x</span><span class="keyword"> <span class="identifier">x</span><span class="special">.</span><span class="identifier">items</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">x</span>
def</span><span class="identifier"> getfunc</span><span class="special">():</span><span class="keyword"> <span class="keyword">def</span> <span class="identifier">getfunc</span><span class="special">():</span>
return</span><span class="identifier"> f</span><span class="special">;</span></tt></pre> <span class="keyword">return</span> <span class="identifier">f</span><span class="special">;</span>
</pre>
<p> <p>
Can be rewritten in C++ using Boost.Python facilities this way:</p> Can be rewritten in C++ using Boost.Python facilities this way:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">object</span><span class="identifier"> x</span><span class="special">,</span><span class="identifier"> object</span><span class="identifier"> y</span><span class="special">)</span><span class="special"> {</span><span class="keyword"> <pre class="programlisting">
if</span><span class="special"> (</span><span class="identifier">y</span><span class="special"> ==</span><span class="string"> "foo"</span><span class="special">)</span><span class="identifier"> <span class="identifier">object</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">object</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span>
x</span><span class="special">.</span><span class="identifier">slice</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">7</span><span class="special">)</span><span class="special"> =</span><span class="string"> "bar"</span><span class="special">;</span><span class="keyword"> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">"foo"</span><span class="special">)</span>
else</span><span class="identifier"> <span class="identifier">x</span><span class="special">.</span><span class="identifier">slice</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">7</span><span class="special">)</span> <span class="special">=</span> <span class="string">"bar"</span><span class="special">;</span>
x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"items"</span><span class="special">)</span><span class="special"> +=</span><span class="identifier"> y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="identifier"> x</span><span class="special">);</span><span class="keyword"> <span class="keyword">else</span>
return</span><span class="identifier"> x</span><span class="special">;</span><span class="special"> <span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"items"</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
}</span><span class="identifier"> <span class="keyword">return</span> <span class="identifier">x</span><span class="special">;</span>
object</span><span class="identifier"> getfunc</span><span class="special">()</span><span class="special"> {</span><span class="keyword"> <span class="special">}</span>
return</span><span class="identifier"> object</span><span class="special">(</span><span class="identifier">f</span><span class="special">);</span><span class="special"> <span class="identifier">object</span> <span class="identifier">getfunc</span><span class="special">()</span> <span class="special">{</span>
}</span></tt></pre> <span class="keyword">return</span> <span class="identifier">object</span><span class="special">(</span><span class="identifier">f</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p> <p>
Apart from cosmetic differences due to the fact that we are writing the Apart from cosmetic differences due to the fact that we are writing the code
code in C++, the look and feel should be immediately apparent to the Python in C++, the look and feel should be immediately apparent to the Python coder.
coder.</p> </p>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div> <a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
<p> <p>
Boost.Python comes with a set of derived <tt class="literal">object</tt> types corresponding to Derived Object typesBoost.Python comes with a set of derived <tt class="literal">object</tt>
that of Python's:</p> types corresponding to that of Python's:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
list list
</li> </li>
<li> <li>
dict dict
</li> </li>
<li> <li>
tuple tuple
</li> </li>
<li> <li>
str str
</li> </li>
<li> <li>
long_ long_
</li> </li>
<li> <li>
enum enum
</li> </li>
</ul></div> </ul></div>
<p> <p>
These derived <tt class="literal">object</tt> types act like real Python types. For instance:</p> These derived <tt class="literal">object</tt> types act like real Python types.
<pre class="programlisting"><tt class="literal"><span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special"> ==&gt;</span><span class="string"> "1"</span></tt></pre> 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">==&gt;</span> <span class="string">"1"</span>
</pre>
<p> <p>
Wherever appropriate, a particular derived <tt class="literal">object</tt> has corresponding Wherever appropriate, a particular derived <tt class="literal">object</tt> has
Python type's methods. For instance, <tt class="literal">dict</tt> has a <tt class="literal">keys()</tt> method:</p> corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
<pre class="programlisting"><tt class="literal"><span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span></tt></pre> has a <tt class="literal">keys()</tt> method:
<p><tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>. Example:</p> </p>
<pre class="programlisting"><tt class="literal"><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></tt></pre> <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>.
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> <p>
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments to functions, In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
subtype matching is required. For example, when a function <tt class="literal">f</tt>, as to functions, subtype matching is required. For example, when a function
declared below, is wrapped, it will only accept instances of Python's <tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
<tt class="literal">str</tt> type and subtypes.</p> instances of Python's <tt class="literal">str</tt> type and subtypes.
<pre class="programlisting"><tt class="literal"><span class="keyword">void</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">str</span><span class="identifier"> name</span><span class="special">)</span><span class="special"> </p>
{</span><span class="identifier"> <pre class="programlisting">
object</span><span class="identifier"> n2</span><span class="special"> =</span><span class="identifier"> name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span><span class="comment"> // NAME = name.upper() <span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
</span><span class="identifier"> str</span><span class="identifier"> NAME</span><span class="special"> =</span><span class="identifier"> name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span><span class="comment"> // better <span class="special">{</span>
</span><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><span class="special"> <span class="identifier">object</span> <span class="identifier">n2</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span> <span class="comment">// NAME = name.upper()
}</span></tt></pre> </span> <span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <span class="comment">// better
</span> <span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%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>
<span class="special">}</span>
</pre>
<p> <p>
In finer detail:</p> In finer detail:
<pre class="programlisting"><tt class="literal"><span class="identifier">str</span><span class="identifier"> NAME</span><span class="special"> =</span><span class="identifier"> name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span></tt></pre> </p>
<pre class="programlisting">
<span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span>
</pre>
<p> <p>
Illustrates that we provide versions of the str type's methods as C++ Illustrates that we provide versions of the str type's methods as C++ member
member functions.</p> functions.
<pre class="programlisting"><tt class="literal"><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></tt></pre> </p>
<pre class="programlisting">
<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> <p>
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format" % x,y,z</tt> Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
in Python, which is useful since there's no easy way to do that in std C++.</p> % x,y,z</tt> in Python, which is useful since there's no easy way to
do that in std C++.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/alert.png"></span><span class="bold"><b>Beware</b></span> the common pitfall of forgetting that the constructors <span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>Beware</b></span> the common pitfall of forgetting that
of most of Python's mutable types make copies, just as in Python. the constructors of most of Python's mutable types make copies, just
</td></tr></tbody> as in Python. </td></tr></tbody>
</table></div> </table></div>
<p> <p>
Python: Python:
</p> </p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special"> =</span><span class="identifier"> dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special">)</span><span class="comment"> # copies x.__dict__ <pre class="programlisting">
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span><span class="comment"> # modifies the copy <span class="special">&gt;&gt;&gt;</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special">)</span> <span class="comment"># copies x.__dict__
</span></tt></pre> </span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span> <span class="comment"># modifies the copy
</span></pre>
<p> <p>
C++: C++:
</p> </p>
<pre class="programlisting"><tt class="literal"><span class="identifier">dict</span><span class="identifier"> d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span><span class="comment"> // copies x.__dict__ <pre class="programlisting">
</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 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></tt></pre> </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="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
<a name="id454735"></a>class_&lt;T&gt; as objects</h2> <a name="id455806"></a>
class_&lt;T&gt; as objects
</h2>
<p> <p>
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_&lt;T&gt;</tt> may Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_&lt;T&gt;</tt>
also be one of these types! The following code snippet wraps the class may also be one of these types! The following code snippet wraps the class
(type) object.</p> (type) object.
</p>
<p> <p>
We can use this to create wrapped instances. Example:</p> We can use this to create wrapped instances. Example:
<pre class="programlisting"><tt class="literal"><span class="identifier">object</span><span class="identifier"> vec345</span><span class="special"> =</span><span class="special"> (</span><span class="identifier"> </p>
class_</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&gt;(</span><span class="string">"Vec2"</span><span class="special">,</span><span class="identifier"> init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</span><span class="special">&gt;())</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span><span class="special"> <span class="identifier">object</span> <span class="identifier">vec345</span> <span class="special">=</span> <span class="special">(</span>
.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span><span class="special"> &amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&gt;(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
)(</span><span class="number">3.0</span><span class="special">,</span><span class="number"> 4.0</span><span class="special">);</span><span class="identifier"> <span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span>
<span class="special">)(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">4.0</span><span class="special">);</span>
assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span><span class="special"> ==</span><span class="number"> 5.0</span><span class="special">);</span></tt></pre> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span> <span class="special">==</span> <span class="number">5.0</span><span class="special">);</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div> <a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
<p> <p>
At some point, we will need to get C++ values out of object instances. This Extracting C++ objectsAt some point, we will need to get C++ values out of
can be achieved with the <tt class="literal">extract&lt;T&gt;</tt> function. Consider the following:</p> object instances. This can be achieved with the <tt class="literal">extract&lt;T&gt;</tt>
<pre class="programlisting"><tt class="literal"><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 function. Consider the following:
</span></tt></pre> </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> <p>
In the code above, we got a compiler error because Boost.Python In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
<tt class="literal">object</tt> can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
we wanted to do above can be achieved by writing:</p> we wanted to do above can be achieved by writing:
<pre class="programlisting"><tt class="literal"><span class="keyword">double</span><span class="identifier"> l</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span><span class="identifier"> </p>
Vec2</span><span class="special">&amp;</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;(</span><span class="identifier">o</span><span class="special">);</span><span class="identifier"> <pre class="programlisting">
assert</span><span class="special">(</span><span class="identifier">l</span><span class="special"> ==</span><span class="identifier"> v</span><span class="special">.</span><span class="identifier">length</span><span class="special">());</span></tt></pre> <span class="keyword">double</span> <span class="identifier">l</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span>
<span class="identifier">Vec2</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;(</span><span class="identifier">o</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">l</span> <span class="special">==</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">length</span><span class="special">());</span>
</pre>
<p> <p>
The first line attempts to extract the "length" attribute of the Boost.Python The first line attempts to extract the "length" attribute of the
<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 Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
by the Boost.Python <tt class="literal">object</tt>.</p> the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
</p>
<p> <p>
Take note that we said "attempt to" above. What if the Boost.Python <tt class="literal">object</tt> Take note that we said "attempt to" above. What if the Boost.Python
does not really hold a <tt class="literal">Vec2</tt> type? This is certainly a possibility considering <tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
the dynamic nature of Python <tt class="literal">object</tt>s. To be on the safe side, if the C++ type type? This is certainly a possibility considering the dynamic nature of Python
can't be extracted, an appropriate exception is thrown. To avoid an exception, <tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
we need to test for extractibility:</p> be extracted, an appropriate exception is thrown. To avoid an exception,
<pre class="programlisting"><tt class="literal"><span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;</span><span class="identifier"> x</span><span class="special">(</span><span class="identifier">o</span><span class="special">);</span><span class="keyword"> we need to test for extractibility:
if</span><span class="special"> (</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">check</span><span class="special">())</span><span class="special"> {</span><span class="identifier"> </p>
Vec2</span><span class="special">&amp;</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> x</span><span class="special">();</span><span class="special"> ...</span></tt></pre> <pre class="programlisting">
<p><span class="inlinemediaobject"><img src="../images/tip.png"></span> The astute reader might have noticed that the <tt class="literal">extract&lt;T&gt;</tt> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">Vec2</span><span class="special">&amp;&gt;</span> <span class="identifier">x</span><span class="special">(</span><span class="identifier">o</span><span class="special">);</span>
facility in fact solves the mutable copying problem:</p> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">check</span><span class="special">())</span> <span class="special">{</span>
<pre class="programlisting"><tt class="literal"><span class="identifier">dict</span><span class="identifier"> d</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special">&lt;</span><span class="identifier">dict</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span><span class="identifier"> <span class="identifier">Vec2</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span><span class="special"> =</span><span class="number"> 3</span><span class="special">;</span>          #<span class="identifier"> modifies</span><span class="identifier"> x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special"> !</span></tt></pre> </pre>
<p><span class="inlinemediaobject"><img src="../images/tip.png"></span>
The astute reader might have noticed that the <tt class="literal">extract&lt;T&gt;</tt>
facility in fact solves the mutable copying problem:
</p>
<pre class="programlisting">
<span class="identifier">dict</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special">&lt;</span><span class="identifier">dict</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span>
<span class="identifier">d</span><span class="special">[</span><span class="string">"whatever"</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies x.__dict__ !
</span></pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.enums"></a>Enums</h3></div></div></div> <a name="python.enums"></a>Enums</h3></div></div></div>
<p> <p>
Boost.Python has a nifty facility to capture and wrap C++ enums. While EnumsBoost.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 has no <tt class="literal">enum</tt> type, we'll often want to expose our
Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes this easy while C++ enums to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility
taking care of the proper conversions from Python's dynamic typing to C++'s makes this easy while taking care of the proper conversions from Python's
strong static typing (in C++, ints cannot be implicitly converted to dynamic typing to C++'s strong static typing (in C++, ints cannot be implicitly
enums). To illustrate, given a C++ enum:</p> converted to enums). To illustrate, given a C++ enum:
<pre class="programlisting"><tt class="literal"><span class="keyword">enum</span><span class="identifier"> choice</span><span class="special"> {</span><span class="identifier"> red</span><span class="special">,</span><span class="identifier"> blue</span><span class="special"> };</span></tt></pre> </p>
<pre class="programlisting">
<span class="keyword">enum</span> <span class="identifier">choice</span> <span class="special">{</span> <span class="identifier">red</span><span class="special">,</span> <span class="identifier">blue</span> <span class="special">};</span>
</pre>
<p> <p>
the construct:</p> the construct:
<pre class="programlisting"><tt class="literal"><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">choice</span><span class="special">&gt;(</span><span class="string">"choice"</span><span class="special">)</span><span class="special"> </p>
.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span><span class="identifier"> red</span><span class="special">)</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span><span class="identifier"> blue</span><span class="special">)</span><span class="special"> <span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">choice</span><span class="special">&gt;(</span><span class="string">"choice"</span><span class="special">)</span>
;</span></tt></pre> <span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
<span class="special">;</span>
</pre>
<p> <p>
can be used to expose to Python. The new enum type is created in the can be used to expose to Python. The new enum type is created in the current
current <tt class="literal">scope()</tt>, which is usually the current module. The snippet above <tt class="literal">scope()</tt>, which is usually the current module. The snippet
creates a Python class derived from Python's <tt class="literal">int</tt> type which is above creates a Python class derived from Python's <tt class="literal">int</tt>
associated with the C++ type passed as its first parameter.</p> type which is associated with the C++ type passed as its first parameter.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span><span class="bold"><b>what is a scope?</b></span><br><br> <span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>what is a scope?</b></span><br><br> The scope is a
The scope is a class that has an class that has an associated global Python object which controls the
associated global Python object which controls the Python namespace in Python namespace in which new extension classes and wrapped functions
which new extension classes and wrapped functions will be defined as will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
</table></div> </table></div>
<p> <p>
You can access those values in Python as</p> You can access those values in Python as
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="identifier"> my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span><span class="identifier"> <pre class="programlisting">
my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
<span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
</pre>
<p> <p>
where my_module is the module where the enum is declared. You can also where my_module is the module where the enum is declared. You can also create
create a new scope around a class:</p> a new scope around a class:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="identifier">scope</span><span class="identifier"> in_X</span><span class="special"> =</span><span class="identifier"> class_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;(</span><span class="string">"X"</span><span class="special">)</span><span class="special"> <pre class="programlisting">
.</span><span class="identifier">def</span><span class="special">(</span><span class="special"> ...</span><span class="special"> )</span><span class="special"> <span class="identifier">scope</span> <span class="identifier">in_X</span> <span class="special">=</span> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;(</span><span class="string">"X"</span><span class="special">)</span>
.</span><span class="identifier">def</span><span class="special">(</span><span class="special"> ...</span><span class="special"> )</span><span class="special"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
;</span><span class="comment"> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
<span class="special">;</span>
// Expose X::nested as X.nested <span class="comment">// Expose X::nested as X.nested
</span><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">&gt;(</span><span class="string">"nested"</span><span class="special">)</span><span class="special"> </span><span class="identifier">enum_</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">&gt;(</span><span class="string">"nested"</span><span class="special">)</span>
.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span><span class="identifier"> red</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span><span class="identifier"> blue</span><span class="special">)</span><span class="special"> <span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
;</span></tt></pre> <span class="special">;</span>
</pre>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -30,109 +30,138 @@
<dt><span class="section"><a href="techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt> <dt><span class="section"><a href="techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt>
</dl></div> </dl></div>
<p> <p>
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</p> General TechniquesHere are presented some useful techniques that you can use
while wrapping code with Boost.Python.
</p>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div> <a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
<p> <p>
A Python package is a collection of modules that provide to the user a certain Creating PackagesA Python package is a collection of modules that provide
functionality. If you're not familiar on how to create packages, a good to the user a certain functionality. If you're not familiar on how to create
introduction to them is provided in the packages, a good introduction to them is provided in the <a href="http://www.python.org/doc/current/tut/node8.html" target="_top">Python
<a href="http://www.python.org/doc/current/tut/node8.html" target="_top">Python Tutorial</a>.</p> Tutorial</a>.
</p>
<p> <p>
But we are wrapping C++ code, using Boost.Python. How can we provide a nice But we are wrapping C++ code, using Boost.Python. How can we provide a nice
package interface to our users? To better explain some concepts, let's work package interface to our users? To better explain some concepts, let's work
with an example.</p> with an example.
</p>
<p> <p>
We have a C++ library that works with sounds: reading and writing various 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) 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, like so:</p> <tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
<pre class="programlisting"><tt class="literal"><span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span><span class="identifier"> like so:
sounds</span><span class="special">::</span><span class="identifier">io</span><span class="identifier"> </p>
sounds</span><span class="special">::</span><span class="identifier">filters</span></tt></pre> <pre class="programlisting">
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span>
<span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span>
</pre>
<p> <p>
We would like to present this same hierarchy to the Python user, allowing him We would like to present this same hierarchy to the Python user, allowing
to write code like this:</p> him to write code like this:
<pre class="programlisting"><tt class="literal"><span class="identifier">import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="identifier"> </p>
sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span> #<span class="identifier"> echo</span><span class="identifier"> is</span><span class="identifier"> a</span><span class="identifier"> C</span><span class="special">++</span><span class="identifier"> function</span></tt></pre> <pre class="programlisting">
<span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span> <span class="comment"># echo is a C++ function
</span></pre>
<p> <p>
The first step is to write the wrapping code. We have to export each module The first step is to write the wrapping code. We have to export each module
separately with Boost.Python, like this:</p> separately with Boost.Python, like this:
<pre class="programlisting"><tt class="literal"><span class="comment">/* file core.cpp */</span><span class="identifier"> </p>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">core</span><span class="special">)</span><span class="special"> <pre class="programlisting">
{</span><span class="comment"> <span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">core</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
/* export everything in the sounds::core namespace */</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">core</span><span class="special">)</span>
...</span><span class="special"> <span class="special">{</span>
}</span><span class="comment"> <span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <span class="identifier">namespace</span> <span class="special">*/</span>
<span class="special">...</span>
<span class="special">}</span>
/* file io.cpp */</span><span class="identifier"> <span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">io</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">io</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">io</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
/* export everything in the sounds::io namespace */</span><span class="special"> <span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span> <span class="identifier">namespace</span> <span class="special">*/</span>
...</span><span class="special"> <span class="special">...</span>
}</span><span class="comment"> <span class="special">}</span>
/* file filters.cpp */</span><span class="identifier"> <span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">filters</span><span class="special">.</span><span class="identifier">cpp</span> <span class="special">*/</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">filters</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">filters</span><span class="special">)</span>
{</span><span class="comment"> <span class="special">{</span>
/* export everything in the sounds::filters namespace */</span><span class="special"> <span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span> <span class="identifier">namespace</span> <span class="special">*/</span>
...</span><span class="special"> <span class="special">...</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
Compiling these files will generate the following Python extensions: Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
<tt class="literal">core.pyd</tt>, <tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.</p> <tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span> The extension <tt class="literal">.pyd</tt> is used for python extension modules, which <span class="inlinemediaobject"><img src="../images/note.png"></span>
are just shared libraries. Using the default for your system, like <tt class="literal">.so</tt> for The extension <tt class="literal">.pyd</tt> is used for python extension
Unix and <tt class="literal">.dll</tt> for Windows, works just as well.</td></tr></tbody> modules, which are just shared libraries. Using the default for your
system, like <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt>
for Windows, works just as well.</td></tr></tbody>
</table></div> </table></div>
<p> <p>
Now, we create this directory structure for our Python package:</p> Now, we create this directory structure for our Python package:
<pre class="programlisting"><tt class="literal">sounds/ </p>
<pre class="programlisting">sounds/
__init__.py __init__.py
core.pyd core.pyd
filters.pyd filters.pyd
io.pyd io.pyd
</tt></pre> </pre>
<p> <p>
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory <tt class="literal">sounds/</tt> is The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
actually a Python package. It can be a empty file, but can also perform some <tt class="literal">sounds/</tt> is actually a Python package. It can be a empty
magic, that will be shown later.</p> file, but can also perform some magic, that will be shown later.
</p>
<p> <p>
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt> into his Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a> into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
and fire up the interpreter:</p> and fire up the interpreter:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span>
&gt;&gt;&gt;</span><span class="identifier"> sound</span><span class="special"> =</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">open</span><span class="special">(</span><span class="string">'file.mp3'</span><span class="special">)</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
&gt;&gt;&gt;</span><span class="identifier"> new_sound</span><span class="special"> =</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">,</span><span class="number"> 1.0</span><span class="special">)</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">sound</span> <span class="special">=</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">open</span><span class="special">(</span><span class="string">'file.mp3'</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">new_sound</span> <span class="special">=</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">,</span> <span class="number">1.0</span><span class="special">)</span>
</pre>
<p> <p>
Nice heh?</p> Nice heh?
</p>
<p> <p>
This is the simplest way to create hierarchies of packages, but it is not very This is the simplest way to create hierarchies of packages, but it is not
flexible. What if we want to add a <span class="emphasis"><em>pure</em></span> Python function to the filters very flexible. What if we want to add a <span class="emphasis"><em>pure</em></span> Python
package, for instance, one that applies 3 filters in a sound object at once? function to the filters package, for instance, one that applies 3 filters
Sure, you can do this in C++ and export it, but why not do so in Python? You in a sound object at once? Sure, you can do this in C++ and export it, but
don't have to recompile the extension modules, plus it will be easier to write why not do so in Python? You don't have to recompile the extension modules,
it.</p> plus it will be easier to write it.
</p>
<p> <p>
If we want this flexibility, we will have to complicate our package hierarchy a If we want this flexibility, we will have to complicate our package hierarchy
little. First, we will have to change the name of the extension modules:</p> a little. First, we will have to change the name of the extension modules:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="comment">/* file core.cpp */</span><span class="identifier"> <pre class="programlisting">
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_core</span><span class="special">)</span><span class="special"> <span class="comment">/* file core.cpp */</span>
{</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_core</span><span class="special">)</span>
...</span><span class="comment"> <span class="special">{</span>
/* export everything in the sounds::core namespace */</span><span class="special"> <span class="special">...</span>
}</span></tt></pre> <span class="comment">/* export everything in the sounds::core namespace */</span>
<span class="special">}</span>
</pre>
<p> <p>
Note that we added an underscore to the module name. The filename will have to Note that we added an underscore to the module name. The filename will have
be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same to the other extension modules. to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
Now, we change our package hierarchy like so:</p> to the other extension modules. Now, we change our package hierarchy like
<pre class="programlisting"><tt class="literal">sounds/ so:
</p>
<pre class="programlisting">sounds/
__init__.py __init__.py
core/ core/
__init__.py __init__.py
@@ -143,220 +172,275 @@ Now, we change our package hierarchy like so:</p>
io/ io/
__init__.py __init__.py
_io.pyd _io.pyd
</tt></pre> </pre>
<p> <p>
Note that we created a directory for each extension module, and added a Note that we created a directory for each extension module, and added a __init__.py
__init__.py to each one. But if we leave it that way, the user will have to to each one. But if we leave it that way, the user will have to access the
access the functions in the core module with this syntax:</p> functions in the core module with this syntax:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span></tt></pre> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span>
<span class="special">&gt;&gt;&gt;</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> <p>
which is not what we want. But here enters the <tt class="literal">__init__.py</tt> magic: everything which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
that is brought to the <tt class="literal">__init__.py</tt> namespace can be accessed directly by the magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
user. So, all we have to do is bring the entire namespace from <tt class="literal">_core.pyd</tt> can be accessed directly by the user. So, all we have to do is bring the
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>:</p> entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> _core</span><span class="keyword"> import</span><span class="special"> *</span></tt></pre> So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
</p>
<pre class="programlisting">
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
</pre>
<p> <p>
We do the same for the other packages. Now the user accesses the functions and We do the same for the other packages. Now the user accesses the functions
classes in the extension modules like before:</p> and classes in the extension modules like before:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special"> </p>
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span></tt></pre> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(...)</span>
</pre>
<p> <p>
with the additional benefit that we can easily add pure Python functions to with the additional benefit that we can easily add pure Python functions
any module, in a way that the user can't tell the difference between a C++ to any module, in a way that the user can't tell the difference between a
function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span> Python function, C++ function and a Python function. Let's add a <span class="emphasis"><em>pure</em></span>
<tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt> package. This function applies both the Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
<tt class="literal">echo</tt> and <tt class="literal">noise</tt> filters in sequence in the given <tt class="literal">sound</tt> object. We package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
create a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our function:</p> filters in sequence in the given <tt class="literal">sound</tt> object. We create
<pre class="programlisting"><tt class="literal"><span class="keyword">import</span><span class="identifier"> _filters</span><span class="keyword"> a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
def</span><span class="identifier"> echo_noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">):</span><span class="identifier"> function:
s</span><span class="special"> =</span><span class="identifier"> _filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span><span class="identifier"> </p>
s</span><span class="special"> =</span><span class="identifier"> _filters</span><span class="special">.</span><span class="identifier">noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span><span class="keyword"> <pre class="programlisting">
return</span><span class="identifier"> s</span></tt></pre> <span class="keyword">import</span> <span class="identifier">_filters</span>
<span class="keyword">def</span> <span class="identifier">echo_noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">):</span>
<span class="identifier">s</span> <span class="special">=</span> <span class="identifier">_filters</span><span class="special">.</span><span class="identifier">echo</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span>
<span class="identifier">s</span> <span class="special">=</span> <span class="identifier">_filters</span><span class="special">.</span><span class="identifier">noise</span><span class="special">(</span><span class="identifier">sound</span><span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">s</span>
</pre>
<p> <p>
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:</p> Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> echo_noise</span><span class="keyword"> import</span><span class="identifier"> echo_noise</span></tt></pre> </p>
<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> <p>
And that's it. The user now accesses this function like any other function And that's it. The user now accesses this function like any other function
from the <tt class="literal">filters</tt> package:</p> from the <tt class="literal">filters</tt> package:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special"> </p>
&gt;&gt;&gt;</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo_noise</span><span class="special">(...)</span></tt></pre> <pre class="programlisting">
<span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">.</span><span class="identifier">echo_noise</span><span class="special">(...)</span>
</pre>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div> <a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
<p> <p>
Thanks to Python's flexibility, you can easily add new methods to a class, Extending Wrapped Objects in PythonThanks to Python's flexibility, you can
even after it was already created:</p> easily add new methods to a class, even after it was already created:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> class</span><span class="identifier"> C</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span><span class="keyword"> pass</span><span class="special"> </p>
&gt;&gt;&gt;</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="comment"> # a regular function <span class="special">&gt;&gt;&gt;</span> <span class="keyword">class</span> <span class="identifier">C</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span> <span class="keyword">pass</span>
</span><span class="special">&gt;&gt;&gt;</span><span class="keyword"> def</span><span class="identifier"> C_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> return</span><span class="string"> 'A C instance!'</span><span class="special"> <span class="special">&gt;&gt;&gt;</span>
&gt;&gt;&gt;</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="comment"># a regular function
&gt;&gt;&gt;</span><span class="comment"> # now we turn it in a member function </span><span class="special">&gt;&gt;&gt;</span> <span class="keyword">def</span> <span class="identifier">C_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span> <span class="keyword">return</span> <span class="string">'A C instance!'</span>
</span><span class="special">&gt;&gt;&gt;</span><span class="identifier"> C</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> C_str</span><span class="special"> <span class="special">&gt;&gt;&gt;</span>
&gt;&gt;&gt;</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="comment"># now we turn it in a member function
&gt;&gt;&gt;</span><span class="identifier"> c</span><span class="special"> =</span><span class="identifier"> C</span><span class="special">()</span><span class="special"> </span><span class="special">&gt;&gt;&gt;</span> <span class="identifier">C</span><span class="special">.</span><span class="identifier">__str__</span> <span class="special">=</span> <span class="identifier">C_str</span>
&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> c</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span>
A</span><span class="identifier"> C</span><span class="identifier"> instance</span><span class="special">!</span><span class="special"> <span class="special">&gt;&gt;&gt;</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C</span><span class="special">()</span>
&gt;&gt;&gt;</span><span class="identifier"> C_str</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">c</span>
A</span><span class="identifier"> C</span><span class="identifier"> instance</span><span class="special">!</span></tt></pre> <span class="identifier">A</span> <span class="identifier">C</span> <span class="identifier">instance</span><span class="special">!</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">C_str</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span>
<span class="identifier">A</span> <span class="identifier">C</span> <span class="identifier">instance</span><span class="special">!</span>
</pre>
<p> <p>
Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p> Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
<p> <p>
We can do the same with classes that were wrapped with Boost.Python. Suppose We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <tt class="literal">point</tt> in C++:</p> we have a class <tt class="literal">point</tt> in C++:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">class</span><span class="identifier"> point</span><span class="special"> {...};</span><span class="identifier"> <pre class="programlisting">
<span class="keyword">class</span> <span class="identifier">point</span> <span class="special">{...};</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
If we are using the technique from the previous session, If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
<a href="techniques.html#python.creating_packages" title="Creating Packages">Creating Packages</a>, we can code directly Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
into <tt class="literal">geom/__init__.py</tt>:</p> </p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="keyword">from</span><span class="identifier"> _geom</span><span class="keyword"> import</span><span class="special"> *</span><span class="comment"> <pre class="programlisting">
<span class="keyword">from</span> <span class="identifier">_geom</span> <span class="keyword">import</span> <span class="special">*</span>
# a regular function <span class="comment"># a regular function
</span><span class="keyword">def</span><span class="identifier"> point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> </span><span class="keyword">def</span> <span class="identifier">point_str</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
return</span><span class="identifier"> str</span><span class="special">((</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">))</span><span class="comment"> <span class="keyword">return</span> <span class="identifier">str</span><span class="special">((</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">self</span><span class="special">.</span><span class="identifier">y</span><span class="special">))</span>
# now we turn it into a member function <span class="comment"># now we turn it into a member function
</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">__str__</span><span class="special"> =</span><span class="identifier"> point_str</span></tt></pre> </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>
<p><span class="bold"><b>All</b></span> point instances created from C++ will also have this member function! </pre>
This technique has several advantages:</p> <p><span class="bold"><b>All</b></span> point instances created from C++ will
also have this member function! This technique has several advantages:
</p>
<div class="itemizedlist"><ul type="disc"> <div class="itemizedlist"><ul type="disc">
<li> <li>
Cut down compile times to zero for these additional functions Cut down compile times to zero for these additional functions
</li> </li>
<li> <li>
Reduce the memory footprint to virtually zero Reduce the memory footprint to virtually zero
</li> </li>
<li> <li>
Minimize the need to recompile Minimize the need to recompile
</li> </li>
<li> <li>
Rapid prototyping (you can move the code to C++ if required without changing the interface) Rapid prototyping (you can move the code to C++ if required without changing
</li> the interface)
</li>
</ul></div> </ul></div>
<p> <p>
You can even add a little syntactic sugar with the use of metaclasses. Let's You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that "injects" methods in other classes.</p> create a special metaclass that "injects" methods in other classes.
<pre class="programlisting"><tt class="literal"><span class="comment"># The one Boost.Python uses for all wrapped classes. </p>
# You can use here any class exported by Boost instead of "point" <pre class="programlisting">
</span><span class="identifier">BoostPythonMetaclass</span><span class="special"> =</span><span class="identifier"> point</span><span class="special">.</span><span class="identifier">__class__</span><span class="keyword"> <span class="comment"># The one Boost.Python uses for all wrapped classes.
</span><span class="comment"># You can use here any class exported by Boost instead of "point"
</span><span class="identifier">BoostPythonMetaclass</span> <span class="special">=</span> <span class="identifier">point</span><span class="special">.</span><span class="identifier">__class__</span>
class</span><span class="identifier"> injector</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span><span class="keyword"> <span class="keyword">class</span> <span class="identifier">injector</span><span class="special">(</span><span class="identifier">object</span><span class="special">):</span>
class</span><span class="identifier"> __metaclass__</span><span class="special">(</span><span class="identifier">BoostPythonMetaclass</span><span class="special">):</span><span class="keyword"> <span class="keyword">class</span> <span class="identifier">__metaclass__</span><span class="special">(</span><span class="identifier">BoostPythonMetaclass</span><span class="special">):</span>
def</span><span class="identifier"> __init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> name</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">,</span><span class="identifier"> dict</span><span class="special">):</span><span class="keyword"> <span class="keyword">def</span> <span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">,</span> <span class="identifier">dict</span><span class="special">):</span>
for</span><span class="identifier"> b</span><span class="keyword"> in</span><span class="identifier"> bases</span><span class="special">:</span><span class="keyword"> <span class="keyword">for</span> <span class="identifier">b</span> <span class="keyword">in</span> <span class="identifier">bases</span><span class="special">:</span>
if</span><span class="identifier"> type</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span><span class="keyword"> not</span><span class="keyword"> in</span><span class="special"> (</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> type</span><span class="special">):</span><span class="keyword"> <span class="keyword">if</span> <span class="identifier">type</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span> <span class="keyword">not</span> <span class="keyword">in</span> <span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">type</span><span class="special">):</span>
for</span><span class="identifier"> k</span><span class="special">,</span><span class="identifier">v</span><span class="keyword"> in</span><span class="identifier"> dict</span><span class="special">.</span><span class="identifier">items</span><span class="special">():</span><span class="identifier"> <span class="keyword">for</span> <span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span> <span class="keyword">in</span> <span class="identifier">dict</span><span class="special">.</span><span class="identifier">items</span><span class="special">():</span>
setattr</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span><span class="special">)</span><span class="keyword"> <span class="identifier">setattr</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span><span class="identifier">k</span><span class="special">,</span><span class="identifier">v</span><span class="special">)</span>
return</span><span class="identifier"> type</span><span class="special">.</span><span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span><span class="identifier"> name</span><span class="special">,</span><span class="identifier"> bases</span><span class="special">,</span><span class="identifier"> dict</span><span class="special">)</span><span class="comment"> <span class="keyword">return</span> <span class="identifier">type</span><span class="special">.</span><span class="identifier">__init__</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">,</span> <span class="identifier">dict</span><span class="special">)</span>
# inject some methods in the point foo <span class="comment"># inject some methods in the point foo
</span><span class="keyword">class</span><span class="identifier"> more_point</span><span class="special">(</span><span class="identifier">injector</span><span class="special">,</span><span class="identifier"> point</span><span class="special">):</span><span class="keyword"> </span><span class="keyword">class</span> <span class="identifier">more_point</span><span class="special">(</span><span class="identifier">injector</span><span class="special">,</span> <span class="identifier">point</span><span class="special">):</span>
def</span><span class="identifier"> __repr__</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> <span class="keyword">def</span> <span class="identifier">__repr__</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
return</span><span class="string"> 'Point(x=%s, y=%s)'</span><span class="special"> %</span><span class="special"> (</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> self</span><span class="special">.</span><span class="identifier">y</span><span class="special">)</span><span class="keyword"> <span class="keyword">return</span> <span class="string">'Point(x=%s, y=%s)'</span> <span class="special">%</span> <span class="special">(</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">self</span><span class="special">.</span><span class="identifier">y</span><span class="special">)</span>
def</span><span class="identifier"> foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span><span class="keyword"> <span class="keyword">def</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
print</span><span class="string"> 'foo!'</span></tt></pre> <span class="keyword">print</span> <span class="string">'foo!'</span>
</pre>
<p> <p>
Now let's see how it got:</p> Now let's see how it got:
<pre class="programlisting"><tt class="literal"><span class="special">&gt;&gt;&gt;</span><span class="keyword"> print</span><span class="identifier"> point</span><span class="special">()</span><span class="identifier"> </p>
Point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">10</span><span class="special">,</span><span class="identifier"> y</span><span class="special">=</span><span class="number">10</span><span class="special">)</span><span class="special"> <pre class="programlisting">
&gt;&gt;&gt;</span><span class="identifier"> point</span><span class="special">().</span><span class="identifier">foo</span><span class="special">()</span><span class="identifier"> <span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">point</span><span class="special">()</span>
foo</span><span class="special">!</span></tt></pre> <span class="identifier">Point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">10</span><span class="special">,</span> <span class="identifier">y</span><span class="special">=</span><span class="number">10</span><span class="special">)</span>
<span class="special">&gt;&gt;&gt;</span> <span class="identifier">point</span><span class="special">().</span><span class="identifier">foo</span><span class="special">()</span>
<span class="identifier">foo</span><span class="special">!</span>
</pre>
<p> <p>
Another useful idea is to replace constructors with factory functions:</p> Another useful idea is to replace constructors with factory functions:
<pre class="programlisting"><tt class="literal"><span class="identifier">_point</span><span class="special"> =</span><span class="identifier"> point</span><span class="keyword"> </p>
<pre class="programlisting">
<span class="identifier">_point</span> <span class="special">=</span> <span class="identifier">point</span>
def</span><span class="identifier"> point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">0</span><span class="special">,</span><span class="identifier"> y</span><span class="special">=</span><span class="number">0</span><span class="special">):</span><span class="keyword"> <span class="keyword">def</span> <span class="identifier">point</span><span class="special">(</span><span class="identifier">x</span><span class="special">=</span><span class="number">0</span><span class="special">,</span> <span class="identifier">y</span><span class="special">=</span><span class="number">0</span><span class="special">):</span>
return</span><span class="identifier"> _point</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier"> y</span><span class="special">)</span></tt></pre> <span class="keyword">return</span> <span class="identifier">_point</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">)</span>
</pre>
<p> <p>
In this simple case there is not much gained, but for constructurs with In this simple case there is not much gained, but for constructurs with many
many overloads and/or arguments this is often a great simplification, again overloads and/or arguments this is often a great simplification, again with
with virtually zero memory footprint and zero compile-time overhead for virtually zero memory footprint and zero compile-time overhead for the keyword
the keyword support.</p> support.
</p>
</div> </div>
<div class="section" lang="en"> <div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title"> <div class="titlepage"><div><div><h3 class="title">
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div> <a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
<p> <p>
If you have ever exported a lot of classes, you know that it takes quite a good Reducing Compiling TimeIf you have ever exported a lot of classes, you know
time to compile the Boost.Python wrappers. Plus the memory consumption can that it takes quite a good time to compile the Boost.Python wrappers. Plus
easily become too high. If this is causing you problems, you can split the the memory consumption can easily become too high. If this is causing you
class_ definitions in multiple files:</p> problems, you can split the class_ definitions in multiple files:
</p>
<p></p> <p></p>
<pre class="programlisting"><tt class="literal"><span class="comment">/* file point.cpp */</span><span class="preprocessor"> <pre class="programlisting">
#include</span><span class="special"> &lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span><span class="preprocessor"> <span class="comment">/* file point.cpp */</span>
#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword"> <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
void</span><span class="identifier"> export_point</span><span class="special">()</span><span class="special"> <span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">()</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
}</span><span class="comment"> <span class="special">}</span>
/* file triangle.cpp */</span><span class="preprocessor"> <span class="comment">/* file triangle.cpp */</span>
#include</span><span class="special"> &lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span><span class="preprocessor"> <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="keyword"> <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
void</span><span class="identifier"> export_triangle</span><span class="special">()</span><span class="special"> <span class="keyword">void</span> <span class="identifier">export_triangle</span><span class="special">()</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <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 <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
macro, and call the various export functions inside it.</p> macro, and call the various export functions inside it.
<pre class="programlisting"><tt class="literal"><span class="keyword">void</span><span class="identifier"> export_point</span><span class="special">();</span><span class="keyword"> </p>
void</span><span class="identifier"> export_triangle</span><span class="special">();</span><span class="identifier"> <pre class="programlisting">
<span class="keyword">void</span> <span class="identifier">export_point</span><span class="special">();</span>
<span class="keyword">void</span> <span class="identifier">export_triangle</span><span class="special">();</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
export_point</span><span class="special">();</span><span class="identifier"> <span class="identifier">export_point</span><span class="special">();</span>
export_triangle</span><span class="special">();</span><span class="special"> <span class="identifier">export_triangle</span><span class="special">();</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
Compiling and linking together all this files produces the same result as the Compiling and linking together all this files produces the same result as
usual approach:</p> the usual approach:
<pre class="programlisting"><tt class="literal"><span class="preprocessor">#include</span><span class="special"> &lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span><span class="preprocessor"> </p>
#include</span><span class="special"> &lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span><span class="preprocessor"> <pre class="programlisting">
#include</span><span class="special"> &lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span><span class="identifier"> <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span><span class="special"> <span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">_geom</span><span class="special">)</span>
{</span><span class="identifier"> <span class="special">{</span>
class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span><span class="identifier"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">&gt;(</span><span class="string">"point"</span><span class="special">)...;</span>
class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special"> <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">triangle</span><span class="special">&gt;(</span><span class="string">"triangle"</span><span class="special">)...;</span>
}</span></tt></pre> <span class="special">}</span>
</pre>
<p> <p>
but the memory is kept under control.</p> but the memory is kept under control.
</p>
<p> <p>
This method is recommended too if you are developing the C++ library and This method is recommended too if you are developing the C++ library and
exporting it to Python at the same time: changes in a class will only demand 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> the compilation of a single cpp, instead of the entire wrapper code.
</p>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>, <span class="inlinemediaobject"><img src="../images/note.png"></span>
take a look at the <tt class="literal">--multiple</tt> option, that generates the wrappers in If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
various files as demonstrated here.</td></tr></tbody> take a look at the <tt class="literal">--multiple</tt> option, that generates
the wrappers in various files as demonstrated here.</td></tr></tbody>
</table></div> </table></div>
<div class="informaltable"><table class="table"> <div class="informaltable"><table class="table">
<colgroup><col></colgroup> <colgroup><col></colgroup>
<tbody><tr><td class="blurb"> <tbody><tr><td class="blurb">
<span class="inlinemediaobject"><img src="../images/note.png"></span> This method is useful too if you are getting the error message <span class="inlinemediaobject"><img src="../images/note.png"></span>
<span class="emphasis"><em>"fatal error C1204:Compiler limit:internal structure overflow"</em></span> when compiling This method is useful too if you are getting the error message <span class="emphasis"><em>"fatal
a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody> error C1204:Compiler limit:internal structure overflow"</em></span>
when compiling a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
</table></div> </table></div>
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td> <td align="left"></td>
<td align="right"><small>Copyright © 2002-2005 Joel de Guzman, David Abrahams</small></td> <td align="right"><small>Copyright © 2002-2005 Joel
de Guzman, David Abrahams</small></td>
</tr></table> </tr></table>
<hr> <hr>
<div class="spirit-nav"> <div class="spirit-nav">

View File

@@ -1249,7 +1249,7 @@ Python:
[python] [python]
>>> d = dict(x.__dict__) # copies x.__dict__ >>> d = dict(x.__dict__) # copies x.__dict__
>>> d['whatever'] # modifies the copy >>> d['whatever'] = 3 # modifies the copy
C++: C++:
[c++] [c++]
@@ -1307,7 +1307,7 @@ __tip__ The astute reader might have noticed that the [^extract<T>]
facility in fact solves the mutable copying problem: facility in fact solves the mutable copying problem:
dict d = extract<dict>(x.attr("__dict__")); dict d = extract<dict>(x.attr("__dict__"));
d['whatever'] = 3; # modifies x.__dict__ ! d["whatever"] = 3; // modifies x.__dict__ !
[endsect] [endsect]
@@ -1754,6 +1754,38 @@ Now, our C++ Wrapper:
.property("pions", range(&F::p_begin, &F::p_end)) .property("pions", range(&F::p_begin, &F::p_end))
.property("bogons", range(&F::b_begin, &F::b_end)); .property("bogons", range(&F::b_begin, &F::b_end));
[*stl_input_iterator]
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 `stl_input_iterator<>`. Consider how we might
implement a function that exposes `std::list<int>::assign()` to
Python:
[c++]
template<typename T>
void list_assign(std::list<T>& l, object o) {
// Turn a Python sequence into an STL input range
stl_input_iterator<T> begin(o), end;
l.assign(begin, end);
}
// Part of the wrapper for list<int>
class_<std::list<int> >("list_int")
.def("assign", &list_assign<int>)
// ...
;
Now in Python, we can assign any integer sequence to `list_int` objects:
[python]
x = list_int();
x.assign([1,2,3,4,5])
[endsect] [endsect]
[section:exception Exception Translation] [section:exception Exception Translation]

View File

@@ -79,7 +79,7 @@ call_method&lt;ResultType&gt;(self_object, "<i>method-name</i>", a1, a2... a<i>N
the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into
new Python objects, but this behavior can be overridden by the use of new Python objects, but this behavior can be overridden by the use of
<code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href= <code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href=
"../../../bind/ref.html#reference_wrapper">ref()</a>:</p> "../../../bind/ref.html">ref()</a>:</p>
<pre> <pre>
class X : boost::noncopyable class X : boost::noncopyable
{ {
@@ -128,7 +128,7 @@ void apply(PyObject* callable, X&amp; x)
<tr> <tr>
<td><code><a href= <td><code><a href=
"../../../bind/ref.html#reference_wrapper">boost::reference_wrapper</a>&lt;T&gt;</code></td> "../../../bind/ref.html">boost::reference_wrapper</a>&lt;T&gt;</code></td>
<td>The Python argument contains a pointer to, rather than a copy of, <td>The Python argument contains a pointer to, rather than a copy of,
<code>x.get()</code>. Note: failure to ensure that no Python code <code>x.get()</code>. Note: failure to ensure that no Python code

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,336 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1st September 2004), see www.w3.org">
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/docstring_options.hpp&gt;</title>
</head>
<body>
<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">Header
&lt;boost/python/docstring_options.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#docstring_options-spec">Class
<code>docstring_options</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#docstring_options-spec-synopsis">Class
<code>docstring_options</code> synopsis</a></dt>
<dt><a href="#docstring_options-spec-ctors">Class
<code>docstring_options</code> constructors</a></dt>
<dt><a href="#docstring_options-spec-dtors">Class
<code>docstring_options</code> destructors</a></dt>
<dt><a href="#docstring_options-spec-modifiers">Class
<code>docstring_options</code> modifiers</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction" id=
"introduction"></a>Introduction</h2>
<p>Boost.Python supports user-defined docstrings with automatic
appending of C++ signatures. These features are enabled by
default. The <code>class docstring_options</code> is available to
selectively suppress the user-defined docstrings, signatures, or
both.</p>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="docstring_options-spec" id=
"docstring_options-spec"></a>Class
<code>docstring_options</code></h3>
<p>Controls the appearance of docstrings of wrapped functions and
member functions for the life-time of the instance. The instances
are noncopyable to eliminate the possibility of surprising side
effects.</p>
<h4><a name="docstring_options-spec-synopsis" id=
"docstring_options-spec-synopsis"></a>Class
<code>docstring_options</code> synopsis</h4>
<pre>
namespace boost { namespace python {
class docstring_options : boost::noncopyable
{
public:
docstring_options(bool show_all=true);
docstring_options(bool show_user_defined, bool show_signatures);
~docstring_options();
void
disable_user_defined();
void
enable_user_defined();
void
disable_signatures();
void
enable_signatures();
void
disable_all();
void
enable_all();
};
}}
</pre>
<h4><a name="docstring_options-spec-ctors" id=
"docstring_options-spec-ctors"></a>Class
<code>docstring_options</code> constructors</h4>
<pre>
docstring_options(bool show_all=true);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows. If
<code>show_all</code> is <code>true</code>, both the
user-defined docstrings and the automatically generated C++
signatures are shown. If <code>show_all</code> is
<code>false</code> the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<pre>
docstring_options(bool show_user_defined, bool show_signatures);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows.
Iff <code>show_user_defined</code> is <code>true</code>, the
user-defined docstrings are shown. Iff
<code>show_signatures</code> is <code>true</code>, C++
signatures are automatically added. If both
<code>show_user_defined</code> and <code>show_signatures</code>
are <code>false</code>, the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<h4><a name="docstring_options-spec-dtors" id=
"docstring_options-spec-dtors"></a>Class
<code>docstring_options</code> destructors</h4>
<pre>
~docstring_options();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Restores the previous state of the
docstring options. In particular, if
<code>docstring_options</code> instances are in nested C++
scopes the settings effective in the enclosing scope are
restored. If the last <code>docstring_options</code> instance
goes out of scope the default "all on" settings are
restored.</dt>
</dl>
<h4><a name="docstring_options-spec-modifiers" id=
"docstring_options-spec-modifiers"></a>Class
<code>docstring_options</code> modifier functions</h4>
<pre>
void disable_user_defined();
void enable_user_defined();
void disable_signatures();
void enable_signatures();
void disable_all();
void enable_all();
</pre>
<dl class="function-semantics">
<dt>These member functions dynamically change the appearance of
docstrings in the code that follows. The
<code>*_user_defined()</code> and <code>*_signatures()</code>
member functions are provided for fine-grained control. The
<code>*_all()</code> member functions are convenient shortcuts
to manipulate both settings simultaneously.</dt>
</dl>
<h2><a name="examples" id="examples"></a>Examples</h2>
<h4>Docstring options defined at compile time</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
void foo() {}
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options(DEMO_DOCSTRING_SHOW_ALL);
def("foo", foo, "foo doc");
}
</pre>If compiled with <code>-DDEMO_DOCSTRING_SHOW_ALL=true</code>:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo.__doc__
foo doc
C++ signature:
foo(void) -&gt; void
</pre>If compiled with
<code>-DDEMO_DOCSTRING_SHOW_ALL=false</code>:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo.__doc__
None
</pre>
<h4>Selective suppressions</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
int foo1(int i) { return i; }
int foo2(long l) { return static_cast&lt;int&gt;(l); }
int foo3(float f) { return static_cast&lt;int&gt;(f); }
int foo4(double d) { return static_cast&lt;int&gt;(d); }
BOOST_PYTHON_MODULE(demo)
{
using namespace boost::python;
docstring_options doc_options;
def("foo1", foo1, arg("i"), "foo1 doc");
doc_options.disable_user_defined();
def("foo2", foo2, arg("l"), "foo2 doc");
doc_options.disable_signatures();
def("foo3", foo3, arg("f"), "foo3 doc");
doc_options.enable_user_defined();
def("foo4", foo4, arg("d"), "foo4 doc");
}
</pre>Python code:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo1.__doc__
foo1 doc
C++ signature:
foo1(int i) -&gt; int
&gt;&gt;&gt; print demo.foo2.__doc__
C++ signature:
foo2(long l) -&gt; int
&gt;&gt;&gt; print demo.foo3.__doc__
None
&gt;&gt;&gt; print demo.foo4.__doc__
foo4 doc
</pre>
<h4>Wrapping from multiple C++ scopes</h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
#include &lt;boost/python/docstring_options.hpp&gt;
int foo1(int i) { return i; }
int foo2(long l) { return static_cast&lt;int&gt;(l); }
int bar1(int i) { return i; }
int bar2(long l) { return static_cast&lt;int&gt;(l); }
namespace {
void wrap_foos()
{
using namespace boost::python;
// no docstring_options here
// -&gt; settings from outer C++ scope are in effect
def("foo1", foo1, arg("i"), "foo1 doc");
def("foo2", foo2, arg("l"), "foo2 doc");
}
void wrap_bars()
{
using namespace boost::python;
bool show_user_defined = true;
bool show_signatures = false;
docstring_options doc_options(show_user_defined, show_signatures);
def("bar1", bar1, arg("i"), "bar1 doc");
def("bar2", bar2, arg("l"), "bar2 doc");
}
}
BOOST_PYTHON_MODULE(demo)
{
boost::python::docstring_options doc_options(false);
wrap_foos();
wrap_bars();
}
</pre>Python code:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo1.__doc__
None
&gt;&gt;&gt; print demo.foo2.__doc__
None
&gt;&gt;&gt; print demo.bar1.__doc__
bar1 doc
&gt;&gt;&gt; print demo.bar2.__doc__
bar2 doc
</pre>
<h4>See also: <code>boost/libs/python/test/docstring.cpp</code>
and <code>docstring.py</code></h4>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
16 January, 2006
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href=
"../../../../people/ralf_w_grosse_kunstleve.htm">Ralf W.
Grosse-Kunstleve</a> 2006.</i></p>
</body>
</html>

View File

@@ -134,7 +134,7 @@ void handle_exception() throw();
"make_function.html#make_function-spec">make_function</a>()</code>, "make_function.html#make_function-spec">make_function</a>()</code>,
<code><a href= <code><a href=
"make_function.html#make_constructor-spec">make_constructor</a>()</code>, "make_function.html#make_constructor-spec">make_constructor</a>()</code>,
<code><a href="def.html#def-spec">def</a>()</code> and <code><a href= <code><a href="def.html#class_-spec-modifiers">def</a>()</code> and <code><a href=
"class.html#def-spec">class_::def</a>()</code>. The second form can be "class.html#def-spec">class_::def</a>()</code>. The second form can be
more convenient to use (see the <a href="#examples">example</a> below), more convenient to use (see the <a href="#examples">example</a> below),
but various compilers have problems when exceptions are rethrown from but various compilers have problems when exceptions are rethrown from

142
doc/v2/exec.html Normal file
View File

@@ -0,0 +1,142 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/exec.hpp&gt;</title>
</head>
<body>
<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">Header &lt;boost/python/exec.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#exec-spec"><code>exec</code></a></dt>
<dt><a href="#exec_file-spec"><code>exec_file</code></a></dt>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Exposes a mechanism for embedding the python interpreter into C++ code.</p>
<h2><a name="functions"></a>Functions</h2>
<h3><a name="exec-spec"></a><code>exec</code></h3>
<pre>
object exec(str code,
object globals = object(),
object locals = object());
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Execute Python source code from <code>code</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 result of executing the code.
</dt>
</dl>
<h3><a name="exec_file-spec"></a><code>exec_file</code></h3>
<pre>
object exec_file(str filename,
object globals = object(),
object locals = object());
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Execute Python source code from the file named by <code>filename</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 result of executing the code.
</dt>
</dl>
<h2><a name="examples"></a>Examples</h2>
<para>The following example demonstrates the use of <function>import</function>
and <function>exec</function> to define a function in python, and later call
it from within C++.</para>
<pre>
#include &lt;iostream&gt;
#include &lt;string&gt;
using namespace boost::python;
void greet()
{
// Retrieve the main module.
object main = import("__main__");
// Retrieve the main module's namespace
object global(main.attr("__dict__"));
// Define greet function in Python.
object result = exec(
"def greet(self): \n"
" return 'Hello from Python!' \n",
global, global);
// Create a reference to it.
object greet = global["greet"];
// Call it.
std::string message = extract&lt;std::string&gt;(greet());
std::cout &lt;&lt; message &lt;&lt; std::endl;
}
</pre>
<para>Instead of embedding the python script into a string,
we could also store it in an a file...</para>
<pre>
def greet(self):
return 'Hello from Python!'
</pre>
<para>... and execute that instead.</para>
<pre>
// ...
// Load the greet function from a file.
object result = exec_file(script, global, global);
// ...
}
</pre>
<p>Revised 01 November, 2005</p>
<p><i>&copy; Copyright Stefan Seefeld 2005.</i></p>
</body>
</html>

View File

@@ -67,8 +67,6 @@
>error C2064: term does not evaluate to a function taking 2 arguments</a> >error C2064: term does not evaluate to a function taking 2 arguments</a>
</dt> </dt>
<dt><a href="#voidptr">How do I handle <tt>void *</tt> conversion?</a></dt>
<dt><a href="#custom_string" <dt><a href="#custom_string"
>How can I automatically convert my custom string type to >How can I automatically convert my custom string type to
and from a Python string?</a></dt> and from a Python string?</a></dt>
@@ -693,29 +691,6 @@ void Export_FXThread()
.def("setAutoDelete", (bool (FXThread::*)(bool)) &amp;FXThread::setAutoDelete)</pre> .def("setAutoDelete", (bool (FXThread::*)(bool)) &amp;FXThread::setAutoDelete)</pre>
<p>(The bug has been reported to Microsoft.)</p> <p>(The bug has been reported to Microsoft.)</p>
<hr>
<h2><a name="voidptr"></a>How do I handle <tt>void *</tt> conversion?</h2>
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
For several reasons Boost.Python does not support <tt>void *</tt> as
an argument or as a return value. However, it is possible to wrap
functions with <tt>void *</tt> arguments or return values using
thin wrappers and the <i>opaque pointer</i> facility. E.g.:
<pre>// Declare the following in each translation unit
struct void_ {};
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void_);
void *foo(int par1, void *par2);
void_ *foo_wrapper(int par1, void_ *par2)
{
return (void_ *) foo(par1, par2);
}
...
BOOST_PYTHON_MODULE(bar)
{
def("foo", &amp;foo_wrapper);
}</pre>
<hr> <hr>
<h2><a name="custom_string"></a>How can I automatically <h2><a name="custom_string"></a>How can I automatically
convert my custom string type to and from a Python string?</h2> convert my custom string type to and from a Python string?</h2>

View File

@@ -110,7 +110,7 @@ using namespace boost::python;
struct X struct X
{ {
X(int x) : v(x) {} X(int x) : v(x) {}
operator int() { return v; } operator int() const { return v; }
int v; int v;
}; };

87
doc/v2/import.html Normal file
View File

@@ -0,0 +1,87 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/import.hpp&gt;</title>
</head>
<body>
<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">Header &lt;boost/python/import.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#functions">Functions</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#import-spec"><code>import</code></a></dt>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Exposes a mechanism for importing python modules.</p>
<h2><a name="functions"></a>Functions</h2>
<h3><a name="import-spec"></a><code>import</code></h3>
<pre>
object import(str name);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Imports the module named by <code>name</code>.</dt>
<dt><b>Returns:</b> An instance of <a href="object.html#object-spec">object</a>
which holds a reference to the imported module.</dt>
</dl>
<h2><a name="examples"></a>Examples</h2>
<para>The following example demonstrates the use of <function>import</function>
to access a function in python, and later call it from within C++.</para>
<pre>
#include &lt;iostream&gt;
#include &lt;string&gt;
using namespace boost::python;
void print_python_version()
{
// Load the sys module.
object sys = import("sys");
// Extract the python version.
std::string version = extract&lt;std::string&gt;(sys.attr("version"));
std::cout &lt;&lt; version &lt;&lt; std::endl;
}
</pre>
<p>Revised 01 November, 2005</p>
<p><i>&copy; Copyright Stefan Seefeld 2005.</i></p>
</body>
</html>

View File

@@ -66,8 +66,8 @@
</dt> </dt>
<dt> <dt>
<a href="#vector_indexing_suite_class">vector_indexing_suite <a href="#vector_indexing_suite_class">vector_indexing_suite
class</a> class<br>
</dt> </a><a href="#map_indexing_suite_class">map_indexing_suite class</a> </dt>
</dl> </dl>
<hr> <hr>
<h2> <h2>
@@ -141,7 +141,7 @@
<h3> <a name="indexing_suite"></a>indexing_suite [ Header &lt;boost/python/indexing/indexing_suite.hpp&gt; <h3> <a name="indexing_suite"></a>indexing_suite [ Header &lt;boost/python/indexing/indexing_suite.hpp&gt;
]</h3> ]</h3>
<p> <p>
The <tt>indexing_suite</tt> class is the base protocol class for the The <tt>indexing_suite</tt> class is the base class for the
management of C++ containers intended to be integrated to Python. The management of C++ containers intended to be integrated to Python. The
objective is make a C++ container look and feel and behave exactly as objective is make a C++ container look and feel and behave exactly as
we'd expect a Python container. The class automatically wraps these we'd expect a Python container. The class automatically wraps these
@@ -275,8 +275,7 @@
The <tt>vector_indexing_suite</tt> class is a predefined The <tt>vector_indexing_suite</tt> class is a predefined
<tt>indexing_suite</tt> derived class designed to wrap <tt>indexing_suite</tt> derived class designed to wrap
<tt>std::vector</tt> (and <tt>std::vector</tt> like [i.e. a class with <tt>std::vector</tt> (and <tt>std::vector</tt> like [i.e. a class with
std::vector interface]) classes (currently, this is the only predefined std::vector interface]) classes. It provides all the policies required by the
suite available). It provides all the policies required by the
<tt>indexing_suite</tt>. <tt>indexing_suite</tt>.
</p> </p>
<p> <p>
@@ -295,22 +294,32 @@
<a href="../../test/vector_indexing_suite.cpp">example in full</a>, <a href="../../test/vector_indexing_suite.cpp">example in full</a>,
along with its <a href="../../test/vector_indexing_suite.py">python along with its <a href="../../test/vector_indexing_suite.py">python
test</a>). test</a>).
</p> </p>
<h3><a name="map_indexing_suite" id="map_indexing_suite"></a>map_indexing_suite [ Header &lt;boost/python/indexing/map_indexing_suite.hpp&gt; ] </h3>
<p> The <tt>map_indexing_suite</tt> class is a predefined <tt>indexing_suite</tt> derived class designed to wrap <tt>std::map</tt> (and <tt>std::map</tt> like [i.e. a class with std::map interface]) classes. It provides all the policies required by the <tt>indexing_suite</tt>. </p>
<p> Example usage: </p>
<pre>
class X {...};
...
class_&lt;std::map&lt;X&gt; &gt;("XMap")
.def(map_indexing_suite&lt;std::map&lt;X&gt; &gt;())
;
</pre>
<p> By default indexed elements are returned by proxy. This can be disabled by supplying <tt>true</tt> in the NoProxy template parameter. <tt>XMap</tt> is now a full-fledged Python container (see the <a href="../../test/map_indexing_suite.cpp">example in full</a>, along with its <a href="../../test/map_indexing_suite.py">python test</a>).</p>
<hr> <hr>
<h2> <h2>
<a name="indexing_suite_class"></a>indexing_suite class <a name="indexing_suite_class"></a>indexing_suite class </h2>
</h2> <h2> <tt>indexing_suite&lt;<br>
<h3> </tt><tt>class Container<br>
<br>
<tt>indexing_suite&lt;<br>
class Container<br>
, class DerivedPolicies<font color="#007F00"><br> , class DerivedPolicies<font color="#007F00"><br>
</font></tt> <tt>, </font></tt> <tt>,
bool NoProxy<br> bool NoProxy<br>
, class Element<br> ,
, class Key<br> bool NoSlice<br>
, class Index</tt> </tt><tt>, class Data<br>
</h3> , class Index<br>
</tt><tt>, class Key</tt></h2>
<table width="100%" border="1"> <table width="100%" border="1">
<tr> <tr>
<td> <td>
@@ -355,36 +364,45 @@
</td> </td>
</tr> </tr>
<tr>
<td> <font color="#007F00"><tt>NoProxy</tt></font> </td>
<td> A boolean </td>
<td> By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying <strong>true</strong> in the <tt>NoProxy</tt> template parameter. </td>
<td> false </td>
</tr>
<tr> <tr>
<td> <td>
<font color="#007F00"><tt>NoProxy</tt></font> <font color="#007F00"><tt>NoSlice</tt></font>
</td> </td>
<td> <td>
A boolean A boolean
</td> </td>
<td> <td>
By default indexed elements have Python reference semantics and are Do not allow slicing. </td>
returned by proxy. This can be disabled by supplying
<strong>true</strong> in the <tt>NoProxy</tt> template parameter.
</td>
<td> <td>
false false
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
<font color="#007F00"><tt>Element</tt></font> <font color="#007F00"><tt>Data</tt></font>
</td> </td>
<td>&nbsp; <td>&nbsp;
</td> </td>
<td> <td>
The container's element type. The container's data type.
</td> </td>
<td> <td>
<tt>Container::value_type</tt> <tt>Container::value_type</tt>
</td> </td>
</tr> </tr>
<tr>
<td> <font color="#007F00"><tt>Index</tt></font> </td>
<td>&nbsp; </td>
<td> The container's index type. </td>
<td> <tt>Container::size_type</tt> </td>
</tr>
<tr> <tr>
<td> <td>
<font color="#007F00"><tt>Key</tt></font> <font color="#007F00"><tt>Key</tt></font>
@@ -399,28 +417,14 @@
<tt>Container::value_type</tt> <tt>Container::value_type</tt>
</td> </td>
</tr> </tr>
<tr> </table>
<td>
<font color="#007F00"><tt>Index</tt></font>
</td>
<td>&nbsp;
</td>
<td>
The container's index type.
</td>
<td>
<tt>Container::size_type</tt>
</td>
</tr>
</table>
<pre> <pre>
template &lt;<br> class Container template &lt;<br> class Container
, class DerivedPolicies , class DerivedPolicies
, bool NoProxy = false , bool NoProxy = false<br> , bool NoSlice = false
, class Element = typename Container::value_type , class Data = typename Container::value_type
, class Key = typename Container::value_type
, class Index = typename Container::size_type , class Index = typename Container::size_type
, class Key = typename Container::value_type
&gt;<br> class indexing_suite &gt;<br> class indexing_suite
: unspecified : unspecified
{ {
@@ -435,23 +439,22 @@
<dl> <dl>
<dd> <dd>
Derived classes provide the hooks needed by Derived classes provide the hooks needed by
the<tt>indexing_suite:</tt> the <tt>indexing_suite:</tt>
</dd> </dd>
</dl> </dl>
<pre> <pre> data_type&amp;
static element_type&amp;
get_item(Container&amp; container, index_type i); get_item(Container&amp; container, index_type i);
static object static object
get_slice(Container&amp; container, index_type from, index_type to); get_slice(Container&amp; container, index_type from, index_type to);
static void static void
set_item(Container&amp; container, index_type i, element_type const&amp; v); set_item(Container&amp; container, index_type i, data_type const&amp; v);
static void static void
set_slice( set_slice(
Container&amp; container, index_type from, Container&amp; container, index_type from,
index_type to, element_type const&amp; v index_type to, data_type const&amp; v
); );
template &lt;class Iter&gt; template &lt;class Iter&gt;
@@ -593,16 +596,16 @@
</tr> </tr>
</table> </table>
<pre> <pre>
template &lt;<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class vector_indexing_suite<br> : public indexing_suite&lt;Container, DerivedPolicies, NoProxy&gt;<br> {<br> public:<br><br> typedef typename Container::value_type element_type;<br> typedef typename Container::value_type key_type;<br> typedef typename Container::size_type index_type;<br> typedef typename Container::size_type size_type;<br> typedef typename Container::difference_type difference_type;<br> <br> static element_type&amp;<br> get_item(Container&amp; container, index_type i); template &lt;<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class vector_indexing_suite : unspecified_base<br> {<br> public:<br><br> typedef typename Container::value_type data_type;<br> typedef typename Container::value_type key_type;<br> typedef typename Container::size_type index_type;<br> typedef typename Container::size_type size_type;<br> typedef typename Container::difference_type difference_type;<br> <br> data_type&amp;<br> get_item(Container&amp; container, index_type i);
static object static object
get_slice(Container&amp; container, index_type from, index_type to); get_slice(Container&amp; container, index_type from, index_type to);
static void<br> set_item(Container&amp; container, index_type i, element_type const&amp; v); static void<br> set_item(Container&amp; container, index_type i, data_type const&amp; v);
static void static void
set_slice(Container&amp; container, index_type from, set_slice(Container&amp; container, index_type from,
index_type to, element_type const&amp; v); index_type to, data_type const&amp; v);
template &lt;class Iter&gt;<br> static void<br> set_slice(Container&amp; container, index_type from,<br> index_type to, Iter first, Iter last); template &lt;class Iter&gt;<br> static void<br> set_slice(Container&amp; container, index_type from,<br> index_type to, Iter first, Iter last);
@@ -624,7 +627,60 @@
adjust_index(index_type current, index_type from, adjust_index(index_type current, index_type from,
index_type to, size_type len); index_type to, size_type len);
}; };
</pre>
</pre>
<h2><a name="vector_indexing_suite_class"></a>map_indexing_suite class </h2>
<h3> Class template <tt><br>
map_indexing_suite&lt;<br>
class <font color="#007F00">Container</font><br>
, bool <font color="#007F00">NoProxy</font><br>
, class <font color="#007F00">DerivedPolicies</font>&gt;</tt> </h3>
<table width="100%" border="1">
<tr>
<td> <strong>Template Parameter</strong><br>
</td>
<td> <strong>Requirements</strong> </td>
<td> <strong>Semantics</strong> </td>
<td> <strong>Default</strong> </td>
</tr>
<tr>
<td> <font color="#007F00"><tt>Container</tt></font> </td>
<td> A class type </td>
<td> The container type to be wrapped to Python. </td>
<td>&nbsp; </td>
</tr>
<tr>
<td> <font color="#007F00"><tt>NoProxy</tt></font> </td>
<td> A boolean </td>
<td> By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying <strong>true</strong> in the <tt>NoProxy</tt> template parameter. </td>
<td> false </td>
</tr>
<tr>
<td> <font color="#007F00"><tt>DerivedPolicies</tt></font> </td>
<td> A subclass of indexing_suite </td>
<td> The <tt>vector_indexing_suite</tt> may still be derived to further tweak any of the predefined policies. Static polymorphism through CRTP (James Coplien. "Curiously Recurring Template Pattern". C++ Report, Feb. 1995) enables the base <tt>indexing_suite</tt> class to call policy function of the most derived class </td>
<td>&nbsp; </td>
</tr>
</table>
<pre>
template &lt;<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class map_indexing_suite : unspecified_base<br> {<br> public:<br><br> typedef typename Container::value_type value_type;<br> typedef typename Container::value_type::second_type data_type;<br> typedef typename Container::key_type key_type;<br> typedef typename Container::key_type index_type;<br> typedef typename Container::size_type size_type;<br> typedef typename Container::difference_type difference_type;<br><br> static data_type&amp;<br> get_item(Container&amp; container, index_type i);
static void<br> set_item(Container&amp; container, index_type i, data_type const&amp; v);
static void
delete_item(Container&amp; container, index_type i);<br>
static size_t
size(Container&amp; container);
static bool
contains(Container&amp; container, key_type const&amp; key);
static bool<br> compare_index(Container&amp; container, index_type a, index_type b);
<br> static index_type
convert_index(Container&amp; container, PyObject* i);
};
</pre>
<hr> <hr>
&copy; Copyright Joel de Guzman 2003. Permission to copy, use, modify, &copy; Copyright Joel de Guzman 2003. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright sell and distribute this document is granted provided this copyright

View File

@@ -45,7 +45,7 @@
<dt><a href="#iterator-spec-synopsis">Class <dt><a href="#iterator-spec-synopsis">Class
<code>iterator</code> synopsis</a></dt> <code>iterator</code> synopsis</a></dt>
<dt><a href="#iterator-spec-ctors">Class template <dt><a href="#iterator-spec-constructors">Class template
<code>iterator</code> constructor</a></dt> <code>iterator</code> constructor</a></dt>
</dl> </dl>
</dd> </dd>

View File

@@ -71,7 +71,7 @@ This macro generates two functions in the scope where it is used:
and <code>void&nbsp;init_module_<i>name</i>()</code>, whose body must and <code>void&nbsp;init_module_<i>name</i>()</code>, whose body must
follow the macro invocation. <code>init_<i>name</i></code> passes follow the macro invocation. <code>init_<i>name</i></code> passes
<code>init_module_<i>name</i></code> to <code><a <code>init_module_<i>name</i></code> to <code><a
href="errors.html#handle_exception">handle_exception</a>()</code> so href="errors.html#handle_exception-spec">handle_exception</a>()</code> so
that any C++ exceptions generated are safely processeed. During the that any C++ exceptions generated are safely processeed. During the
body of <code>init_<i>name</i></code>, the current <code><a body of <code>init_<i>name</i></code>, the current <code><a
href="scope.html#scope-spec">scope</a></code> refers to the module href="scope.html#scope-spec">scope</a></code> refers to the module

View File

@@ -183,10 +183,15 @@
<dt><a href="#binary-spec">binary operations</a></dt> <dt><a href="#binary-spec">binary operations</a></dt>
<dt><a href="#assignment-spec">assignment operations</a></dt> <dt><a href="#assignment-spec">assignment operations</a></dt>
</dl> </dl>
<dl class="page-index"> <dl class="page-index">
<dt><a href="#operators-spec">operators</a></dt> <dt><a href="#object_operators-spec">operators</a></dt>
</dl>
<dl class="page-index">
<dt><a href="#len-spec">len()</a></dt>
</dl> </dl>
</dd> </dd>
@@ -232,7 +237,7 @@ x[slice(_,_,-1)]
<p>The policies which are used for proxies representing an attribute <p>The policies which are used for proxies representing an attribute
access to a <code>const&nbsp;object</code>.</p> access to a <code>const&nbsp;object</code>.</p>
<h4><a name="class-spec-synopsis"></a>Class <h4><a name="const_attribute_policies-spec-synopsis"></a>Class
<code>const_attribute_policies</code> synopsis</h4> <code>const_attribute_policies</code> synopsis</h4>
<pre> <pre>
namespace boost { namespace python { namespace api namespace boost { namespace python { namespace api
@@ -900,7 +905,16 @@ template&lt;class R&gt; object&amp; operator|=(object&amp;l,R const&amp;r);
<dt><b>Returns:</b> <code>l</code>.</dt> <dt><b>Returns:</b> <code>l</code>.</dt>
</dl> </dl>
<h2><a name="examples"></a>Example</h2> <pre>
inline long len(object const&amp; obj);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> PyObject_Length(obj.ptr()) </dt>
<dt><b>Returns:</b> len() of object.</dt>
</dl>
<h2><a name="examples"></a>Example</h2>
Python code: Python code:
<pre> <pre>
def sum_items(seq): def sum_items(seq):
@@ -914,20 +928,18 @@ def sum_items(seq):
object sum_items(object seq) object sum_items(object seq)
{ {
object result = object(0); object result = object(0);
for (int i = 0; i &lt; seq.attr("__len__")(); ++i) for (int i = 0; i &lt; len(seq); ++i)
result += seq[i]; result += seq[i];
return result; return result;
} }
</pre> </pre>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan --> <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002 13 January, 2006
<!--webbot bot="Timestamp" endspan i-checksum="39359" --> <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p> </p>
<p><i>&copy; Copyright <a href= <p><i>&copy; Copyright <a href=
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p> "../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2006.</i></p>
</body> </body>
</html> </html>

View File

@@ -123,7 +123,7 @@ explicit opaque_pointer_converter(char const* name);
<h2><a name="examples"></a>Example</h2> <h2><a name="examples"></a>Example</h2>
please see example for <a href="return_opaque_pointer.html#example"> please see example for <a href="return_opaque_pointer.html#examples">
return_opaque_pointer</a>. return_opaque_pointer</a>.
<h2><a name="see-also"></a>See Also</h2> <h2><a name="see-also"></a>See Also</h2>

View File

@@ -57,7 +57,7 @@
<dt><a href="#self_t-spec-value-unary-ops">Class <dt><a href="#self_t-spec-value-unary-ops">Class
<code>self_t</code> unary operations</a></dt> <code>self_t</code> unary operations</a></dt>
<dt><a href="#self_t-spec-value-value-ops">Class <dt><a href="#self_t-spec-value-ops">Class
<code>self_t</code> value operations</a></dt> <code>self_t</code> value operations</a></dt>
</dl> </dl>
</dd> </dd>

View File

@@ -92,8 +92,8 @@ following examples.
<hr> <hr>
<h2>Examples</h2> <h2>Examples</h2>
There are three files in <a href="../../test/" There are three files in
><tt>boost/libs/python/test</tt></a> that show how to <tt>boost/libs/python/test</tt> that show how to
provide pickle support. provide pickle support.
<hr> <hr>

View File

@@ -51,13 +51,11 @@
3.1, and 3.2 on <a href="http://www.redhat.com">RedHat Linux 7.3</a> 3.1, and 3.2 on <a href="http://www.redhat.com">RedHat Linux 7.3</a>
for Intel x86</dt> for Intel x86</dt>
<dt><a href= <dt>Tru64 CXX 6.5.1 on OSF v. 5.1 for Dec/Compaq
"http://www.tru64unix.compaq.com/cplus/index.html">Tru64 CXX Alpha</dt>
6.5.1</a> on OSF v. 5.1 for Dec/Compaq Alpha</dt>
<dt><a href= <dt>
"http://www.sgi.com/developers/devtools/languages/mipspro.html"> MIPSPro 7.3.1.2m on <a href=
MIPSPro 7.3.1.2m</a> on <a href=
"http://www.sgi.com/software/irix6.5/">IRIX 6.5</a> for SGI "http://www.sgi.com/software/irix6.5/">IRIX 6.5</a> for SGI
mips</dt> mips</dt>
@@ -70,21 +68,16 @@
<dd> <dd>
<dl> <dl>
<dt><a href= <dt>KCC 3.4d on OSF v. 5.1 for Dec/Compaq Alpha</dt>
"http://developer.intel.com/software/products/kcc/">KCC
3.4d</a> on OSF v. 5.1 for Dec/Compaq Alpha</dt>
<dt><a href= <dt>KCC 3.4d</a> on AIX</dt>
"http://developer.intel.com/software/products/kcc/">KCC
3.4d</a> on AIX</dt>
</dl> </dl>
</dd> </dd>
</dl> </dl>
<br> <br>
</dd> </dd>
<dt><a href="http://www.microsoft.com/windowsxp/default.asp">Microsoft <dt>Microsoft Windows XP Professional with Python <a href=
Windows XP Professional</a> with Python <a href=
"http://www.python.org/2.2">2.2</a>, <a href= "http://www.python.org/2.2">2.2</a>, <a href=
"http://www.python.org/2.2.1">2.2.1</a>, and <a href= "http://www.python.org/2.2.1">2.2.1</a>, and <a href=
"http://www.python.org/2.2.2">2.2.2b1</a>:</dt> "http://www.python.org/2.2.2">2.2.2b1</a>:</dt>

View File

@@ -45,8 +45,8 @@
<p><code>&lt;boost/python/pointee.hpp&gt;</code> introduces a <p><code>&lt;boost/python/pointee.hpp&gt;</code> introduces a
traits <a traits <a
href="../../../mpl/doc/index.html#metafunctions">metafunction</a> href="../../../mpl/doc/refmanual/metafunction.html">metafunction</a>
template <code>pointee&lt;T&gt;</code> which can be used to extract the &quot;pointed-to&quot; type from the type of a pointer or smart pointer. template <code>pointee&lt;T&gt;</code> that can be used to extract the &quot;pointed-to&quot; type from the type of a pointer or smart pointer.
<h2><a name="classes"></a>Classes</h2> <h2><a name="classes"></a>Classes</h2>

View File

@@ -60,6 +60,8 @@
<dt><a href="#type_conversion">To/From Python Type Conversion</a></dt> <dt><a href="#type_conversion">To/From Python Type Conversion</a></dt>
<dt><a href="#embedding">Embedding</a></dt>
<dt><a href="#utility">Utility and Infrastructure</a></dt> <dt><a href="#utility">Utility and Infrastructure</a></dt>
<dt><a href="#topics">Topics</a></dt> <dt><a href="#topics">Topics</a></dt>
@@ -76,7 +78,7 @@
<dt><a href= <dt><a href=
"Dereferenceable.html#Dereferenceable-concept">Dereferenceable</a></dt> "Dereferenceable.html#Dereferenceable-concept">Dereferenceable</a></dt>
<dt><a href="Dereferenceable.html#Extractor-concept">Extractor</a></dt> <dt><a href="Extractor.html#Extractor-concept">Extractor</a></dt>
<dt><a href= <dt><a href=
"HolderGenerator.html#HolderGenerator-concept">HolderGenerator</a></dt> "HolderGenerator.html#HolderGenerator-concept">HolderGenerator</a></dt>
@@ -135,6 +137,14 @@
</dl> </dl>
</dd> </dd>
<dt><a href="docstring_options.html">docstring_options.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href="docstring_options.html#classes">Classes</a></dt>
</dl>
</dd>
<dt><a href="enum.html">enum.hpp</a></dt> <dt><a href="enum.html">enum.hpp</a></dt>
<dd> <dd>
@@ -291,6 +301,20 @@
</dl> </dl>
</dd> </dd>
<dt><a href="stl_iterator.html">stl_iterator.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href="stl_iterator.html#classes">Classes</a></dt>
<dd>
<dl class="index">
<dt><a href="stl_iterator.html#stl_input_iterator-spec">stl_input_iterator</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="wrapper.html">wrapper.hpp</a></dt> <dt><a href="wrapper.html">wrapper.hpp</a></dt>
<dd> <dd>
@@ -939,6 +963,39 @@
</dd> </dd>
</dl> </dl>
<h2><a name="embedding">Embedding</a></h2>
<dl class="index">
<dt><a href="exec.html">exec.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href="exec.html#functions">Functions</a></dt>
<dd>
<dl class="index">
<dt><a href="exec.html#exec-spec">exec</a></dt>
<dt><a href="exec.html#exec_file-spec">exec_file</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="import.html">import.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href="import.html#functions">Functions</a></dt>
<dd>
<dl class="index">
<dt><a href="import.html#import-spec">import</a></dt>
</dl>
</dd>
</dl>
</dd>
</dl>
<h2><a name="utility">Utility and Infrastructure</a></h2> <h2><a name="utility">Utility and Infrastructure</a></h2>
<dl> <dl>
@@ -981,7 +1038,7 @@
<dd> <dd>
<dl class="index"> <dl class="index">
<dt>class template <a href= <dt>class template <a href=
"pointee.html#pointee">pointee</a></dt> "pointee.html#pointee-spec">pointee</a></dt>
</dl> </dl>
</dd> </dd>
</dl> </dl>

View File

@@ -102,9 +102,9 @@ template &lt;class T&gt; struct apply
<dt><b>Returns:</b> <code>typedef <a href= <dt><b>Returns:</b> <code>typedef <a href=
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a>&lt;T,V&gt; "to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a>&lt;T,V&gt;
type</code>, where <code>V</code> is a <a href= type</code>, where <code>V</code> is a class whose
"to_python_indirect.html#HolderObjectGenerator">HolderObjectGenerator</a> static <code>execute</code> function constructs an instance
which constructs an instance holder containing an <i>unowned</i> holder containing an <i>unowned</i>
<code>U*</code> pointing to the referent of the wrapped function's <code>U*</code> pointing to the referent of the wrapped function's
return value.</dt> return value.</dt>
</dl> </dl>

View File

@@ -137,8 +137,8 @@ namespace boost { namespace python
}} }}
</pre> </pre>
<h4><a name="default_call_policies-spec-statics"></a>Class <h4><a name="return_internal_reference-spec-statics"></a>Class
<code>default_call_policies</code> static functions</h4> <code>return_internal_reference</code> static functions</h4>
<pre> <pre>
PyObject* postcall(PyObject* args, PyObject* result); PyObject* postcall(PyObject* args, PyObject* result);
</pre> </pre>

View File

@@ -121,13 +121,14 @@ scope();
<p>C++ Module definition:</p> <p>C++ Module definition:</p>
<pre> <pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/class.hpp&gt; #include &lt;boost/python/class.hpp&gt;
#include &lt;boost/python/scope.hpp&gt; #include &lt;boost/python/scope.hpp&gt;
using namespace boost::python; using namespace boost::python;
struct X struct X
{ {
void f(); void f() {}
struct Y { int g() { return 42; } }; struct Y { int g() { return 42; } };
}; };
@@ -145,8 +146,8 @@ BOOST_PYTHON_MODULE(nested)
; ;
// Define a class Y in the current scope, X // Define a class Y in the current scope, X
class_&lt;Y&gt;("Y") class_&lt;X::Y&gt;("Y")
.def("g", &amp;Y::g) .def("g", &amp;X::Y::g)
; ;
} }
</pre> </pre>

View File

@@ -53,7 +53,7 @@ for the Python <a
href="http://www.python.org/doc/2.3.3/api/slice-objects.html">slice</a> href="http://www.python.org/doc/2.3.3/api/slice-objects.html">slice</a>
type.</p> type.</p>
<h2><a name="classes"></a>Classes</h2> <h2><a name="classes"></a>Classes</h2>
<h3><a name="class-spec"></a>Class <code>slice</code></h3> <h3><a name="slice-spec"></a>Class <code>slice</code></h3>
<p>Exposes the extended slicing protocol by wrapping the built-in slice <p>Exposes the extended slicing protocol by wrapping the built-in slice
type. The semantics of the constructors and member functions defined type. The semantics of the constructors and member functions defined
below can be fully understood by reading the <a below can be fully understood by reading the <a
@@ -134,7 +134,7 @@ slice(Int1 start, Int2 stop, Int3 step);
<dt><b>Effects:</b> constructs a new slice with start stop and step <dt><b>Effects:</b> constructs a new slice with start stop and step
values.&nbsp; Equivalent to the slice object created values.&nbsp; Equivalent to the slice object created
by the built-in Python function <code><a by the built-in Python function <code><a
href="http://www.python.org/doc/current/lib/built-in-functions.html#12h-62">slice(start,stop,step)</a></code>, href="http://www.python.org/doc/current/lib/built-in-funcs.html">slice(start,stop,step)</a></code>,
or as part of the Python expression <code>base[start:stop:step]</code>.</dt> or as part of the Python expression <code>base[start:stop:step]</code>.</dt>
<dt><b>Throws:</b> <code>error_already_set</code> and sets a Python <code>TypeError</code> <dt><b>Throws:</b> <code>error_already_set</code> and sets a Python <code>TypeError</code>
exception if no conversion is possible from the arguments to type exception if no conversion is possible from the arguments to type

270
doc/v2/stl_iterator.html Executable file
View File

@@ -0,0 +1,270 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Python - &lt;boost/python/stl_iterator.hpp&gt;</title>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 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">
</head>
<body>
<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">Header &lt;boost/python/stl_iterator.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#stl_input_iterator-spec">Class template
<code>stl_input_iterator</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#stl_input_iterator-spec-synopsis">Class
<code>stl_input_iterator</code> synopsis</a></dt>
<dt><a href="#stl_input_iterator-spec-constructors">Class template
<code>stl_input_iterator</code> constructors</a></dt>
<dt><a href="#stl_input_iterator-spec-modifiers">Class template
<code>stl_input_iterator</code> modifiers</a></dt>
<dt><a href="#stl_input_iterator-spec-observers">Class template
<code>stl_input_iterator</code> observers</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p><code>&lt;boost/python/stl_iterator.hpp&gt;</code> provides types
for creating <a href="http://www.sgi.com/tech/stl/Iterators.html">C++
Iterators</a> from <a href="http://www.python.org/doc/current/lib/typeiter.html">
Python iterables</a>.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="stl_input_iterator-spec"></a>Class Template
<code>stl_input_iterator</code></h3>
<p>Instances of <code>stl_input_iterator&lt;T&gt;</code> hold a Python
iterator and adapt it for use with STL algorithms.
<code>stl_input_iterator&lt;T&gt;</code> satisfies the requirements for
an <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
</p>
<table border="1" summary="stl_input_iterator template parameters">
<tr>
<th>Template Parameter</th>
<th>Requirements</th>
<th>Semantics</th>
<th>Default</th>
</tr>
<tr>
<td><code>ValueType</code></td>
<td><code>ValueType</code> must be CopyConstructible.</td>
<td>Dereferencing an instance of <code>stl_input_iterator&lt;ValueType&gt;</code>
will return an rvalue of type <code>ValueType</code>.</td>
<td><i>None</i></td>
</tr>
</table>
<h4><a name="stl_input_iterator-spec-synopsis"></a>Class Template stl_input_iterator
synopsis</h4>
<pre>
namespace boost { namespace python
{
template &lt;class ValueType&gt;
struct stl_input_iterator
{
typedef std::ptrdiff_t difference_type;
typedef ValueType value_type;
typedef ValueType* pointer;
typedef ValueType reference;
typedef std::input_iterator_tag iterator_category;
stl_input_iterator();
stl_input_iterator(<a href="object.html#object-spec">object</a> const&amp; ob);
stl_input_iterator&amp; operator++();
stl_input_iterator operator++(int);
ValueType operator*() const;
friend bool operator==(stl_input_iterator const&amp; lhs, stl_input_iterator const&amp; rhs);
friend bool operator!=(stl_input_iterator const&amp; lhs, stl_input_iterator const&amp; rhs);
private:
<a href="object.html#object-spec">object</a> it; // For exposition only
<a href="object.html#object-spec">object</a> ob; // For exposition only
};
}}
</pre>
<h4>
<a name="stl_input_iterator-spec-constructors"></a>Class Template <code>stl_input_iterator</code>
constructors
</h4>
<pre>
stl_input_iterator()
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Creates a past-the-end input iterator, useful for signifying the end of a sequence.
</dt>
<dt><b>Postconditions:</b> <code>this</code> is past-the-end.</dt>
<dt><b>Throws:</b> Nothing.</dt>
</dl>
<pre>
stl_input_iterator(object const&amp; ob)
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Calls <code>ob.attr("__iter__")()</code> and stores the resulting Python iterator
object in <code>this-&gt;it</code>. Then, calls <code>this-&gt;it.attr("next")()</code> and
stores the result in <code>this-&gt;ob</code>. If the sequence is exhausted, sets
<code>this-&gt;ob</code> to <code>object()</code>.
</dt>
<dt><b>Postconditions:</b> <code>this</code> is a dereferenceable or past-the-end.</dt>
</dl>
<h4>
<a name="stl_input_iterator-spec-modifiers"></a>Class Template <code>stl_input_iterator</code>
modifiers
</h4>
<pre>
stl_input_iterator&amp; operator++()
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Calls <code>this-&gt;it.attr("next")()</code> and stores the result in
<code>this-&gt;ob</code>. If the sequence is exhausted, sets <code>this-&gt;ob</code>
to <code>object()</code>.
</dt>
<dt><b>Postconditions:</b> <code>this</code> is a dereferenceable or past-the-end.</dt>
<dt><b>Returns:</b> <code>*this</code>.</dt>
</dl>
<pre>
stl_input_iterator operator++(int)
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
<code>stl_input_iterator tmp = *this; ++*this; return tmp;</code>
</dt>
<dt><b>Postconditions:</b> <code>this</code> is a dereferenceable or past-the-end.</dt>
</dl>
<h4><a name="stl_input_iterator-spec-observers"></a>Class Template<code>stl_input_iterator</code>
observers</h4>
<pre>
ValueType operator*() const
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Returns the current element in the sequence.
</dt>
<dt><b>Returns:</b>
<code>extract&lt;ValueType&gt;(this-&gt;ob);</code>
</dt>
</dl>
<pre>
friend bool operator==(stl_input_iterator const&amp; lhs, stl_input_iterator const&amp; rhs)
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Returns true if both iterators are dereferenceable or if both iterators are past-the-end,
false otherwise.
</dt>
<dt><b>Returns:</b>
<code>(lhs.ob == object()) == (rhs.ob == object())</code>
</dt>
</dl>
<pre>
friend bool operator!=(stl_input_iterator const&amp; lhs, stl_input_iterator const&amp; rhs)
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
Returns false if both iterators are dereferenceable or if both iterators are past-the-end,
true otherwise.
</dt>
<dt><b>Returns:</b>
<code>!(lhs == rhs)</code>
</dt>
</dl>
<h2><a name="examples"></a>Examples</h2>
<pre>
#include &lt;boost/python/object.hpp&gt;
#include &lt;boost/python/stl_iterator.hpp&gt;
#include &lt;list&gt;
using namespace boost::python;
std::list&lt;int&gt; sequence_to_int_list(object const&amp; ob)
{
stl_input_iterator&lt;int&gt; begin(ob), end;
return std::list&lt;int&gt;(begin, end);
}
</pre>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->30
October, 2005
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>© Copyright Eric Niebler 2005.</i></p>
</body>
</html>

View File

@@ -1,70 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
// See http://www.boost.org/libs/python for documentation.
#ifndef PYTHON_DWA2002810_HPP
# define PYTHON_DWA2002810_HPP
# include <boost/python/args.hpp>
# include <boost/python/args_fwd.hpp>
# include <boost/python/back_reference.hpp>
# include <boost/python/bases.hpp>
# include <boost/python/borrowed.hpp>
# include <boost/python/call.hpp>
# include <boost/python/call_method.hpp>
# include <boost/python/class.hpp>
# include <boost/python/copy_const_reference.hpp>
# include <boost/python/copy_non_const_reference.hpp>
# include <boost/python/data_members.hpp>
# include <boost/python/def.hpp>
# include <boost/python/default_call_policies.hpp>
# include <boost/python/dict.hpp>
# include <boost/python/enum.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/exception_translator.hpp>
# include <boost/python/extract.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/has_back_reference.hpp>
# include <boost/python/implicit.hpp>
# include <boost/python/init.hpp>
# include <boost/python/instance_holder.hpp>
# include <boost/python/iterator.hpp>
# include <boost/python/list.hpp>
# include <boost/python/long.hpp>
# include <boost/python/lvalue_from_pytype.hpp>
# include <boost/python/make_constructor.hpp>
# include <boost/python/make_function.hpp>
# include <boost/python/manage_new_object.hpp>
# include <boost/python/module.hpp>
# include <boost/python/numeric.hpp>
# include <boost/python/object.hpp>
# include <boost/python/object_protocol.hpp>
# include <boost/python/object_protocol_core.hpp>
# include <boost/python/opaque_pointer_converter.hpp>
# include <boost/python/operators.hpp>
# include <boost/python/other.hpp>
# include <boost/python/overloads.hpp>
# include <boost/python/pointee.hpp>
# include <boost/python/pure_virtual.hpp>
# include <boost/python/ptr.hpp>
# include <boost/python/reference_existing_object.hpp>
# include <boost/python/register_ptr_to_python.hpp>
# include <boost/python/return_arg.hpp>
# include <boost/python/return_internal_reference.hpp>
# include <boost/python/return_opaque_pointer.hpp>
# include <boost/python/return_value_policy.hpp>
# include <boost/python/scope.hpp>
# include <boost/python/self.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/str.hpp>
# include <boost/python/to_python_converter.hpp>
# include <boost/python/to_python_indirect.hpp>
# include <boost/python/to_python_value.hpp>
# include <boost/python/tuple.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/with_custodian_and_ward.hpp>
#endif // PYTHON_DWA2002810_HPP

View File

@@ -116,7 +116,7 @@ BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUn
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<int>(x.size()))) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<int>(x.size())))
# ifndef BOOST_NO_STD_WSTRING #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<int>(x.size()))) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<int>(x.size())))
# endif # endif
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))

View File

@@ -9,7 +9,10 @@
# include <boost/python/converter/registrations.hpp> # include <boost/python/converter/registrations.hpp>
# include <boost/type_traits/transform_traits.hpp> # include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/cv_traits.hpp> # include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/is_void.hpp>
# include <boost/detail/workaround.hpp> # include <boost/detail/workaround.hpp>
# include <boost/python/type_id.hpp>
# include <boost/type.hpp>
namespace boost { namespace boost {
@@ -77,15 +80,30 @@ namespace detail
} }
template <class T> template <class T>
registration const& inline registration const&
registry_lookup(T&(*)()) registry_lookup2(T&(*)())
{ {
detail::register_shared_ptr1((T*)0); detail::register_shared_ptr1((T*)0);
return registry::lookup(type_id<T&>()); return registry::lookup(type_id<T&>());
} }
template <class T> template <class T>
registration const& registered_base<T>::converters = detail::registry_lookup((T(*)())0); inline registration const&
registry_lookup1(type<T>)
{
return registry_lookup2((T(*)())0);
}
inline registration const&
registry_lookup1(type<const volatile void>)
{
detail::register_shared_ptr1((void*)0);
return registry::lookup(type_id<void>());
}
template <class T>
registration const& registered_base<T>::converters = detail::registry_lookup1(type<T>());
} }
}}} // namespace boost::python::converter }}} // namespace boost::python::converter

View File

@@ -2,17 +2,14 @@
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// DEPRECATED HEADER (2006 Jan 12)
// Provided only for backward compatibility.
// The boost::python::len() function is now defined in object.hpp.
#ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP #ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP
#define BOOST_PYTHON_API_PLACE_HOLDER_HPP #define BOOST_PYTHON_API_PLACE_HOLDER_HPP
namespace boost { namespace python { #include <boost/python/object.hpp>
inline long len(object const& obj)
{
long result = PyObject_Length(obj.ptr());
if (PyErr_Occurred()) throw_error_already_set();
return result;
}
}} // namespace boost::python
#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP #endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP

View File

@@ -29,14 +29,14 @@
# endif # endif
# if defined(BOOST_MSVC) # if defined(BOOST_MSVC)
# if _MSC_VER <= 1200 # if _MSC_VER < 1300
# define BOOST_MSVC6_OR_EARLIER 1 # define BOOST_MSVC6_OR_EARLIER 1
# endif # endif
# pragma warning (disable : 4786) // disable truncated debug symbols # pragma warning (disable : 4786) // disable truncated debug symbols
# pragma warning (disable : 4251) // disable exported dll function # pragma warning (disable : 4251) // disable exported dll function
# pragma warning (disable : 4800) //'int' : forcing value to bool 'true' or 'false' # pragma warning (disable : 4800) //'int' : forcing value to bool 'true' or 'false'
# pragma warning (disable : 4275) // non dll-interface class # pragma warning (disable : 4275) // non dll-interface class
# elif defined(__ICL) && __ICL < 600 // Intel C++ 5 # elif defined(__ICL) && __ICL < 600 // Intel C++ 5
@@ -68,13 +68,13 @@
#if defined(BOOST_PYTHON_DYNAMIC_LIB) #if defined(BOOST_PYTHON_DYNAMIC_LIB)
# if !defined(_WIN32) && !defined(__CYGWIN__) \ # if !defined(_WIN32) && !defined(__CYGWIN__) \
&& defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >=5 \ && !defined(BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY) \
&& !defined(BOOST_PYTHON_GCC_SYMBOL_VISIBILITY) && BOOST_WORKAROUND(__GNUC__, >= 3) && (__GNUC_MINOR__ >=5 || __GNUC__ > 3)
# define BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY # define BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY 1
# endif # endif
# if defined(BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY) # if BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# if defined(BOOST_PYTHON_SOURCE) # if defined(BOOST_PYTHON_SOURCE)
# define BOOST_PYTHON_DECL __attribute__ ((visibility("default"))) # define BOOST_PYTHON_DECL __attribute__ ((visibility("default")))
# define BOOST_PYTHON_BUILD_DLL # define BOOST_PYTHON_BUILD_DLL

View File

@@ -11,7 +11,7 @@
namespace boost { namespace python { namespace detail { namespace boost { namespace python { namespace detail {
struct BOOST_PYTHON_DECL exception_handler; struct BOOST_PYTHON_DECL_FORWARD exception_handler;
typedef function2<bool, exception_handler const&, function0<void> const&> handler_function; typedef function2<bool, exception_handler const&, function0<void> const&> handler_function;

View File

@@ -10,7 +10,7 @@ namespace boost { namespace python { namespace detail {
// Allows us to force the argument to be instantiated without // Allows us to force the argument to be instantiated without
// incurring unused variable warnings // incurring unused variable warnings
# if !defined(BOOST_MSVC) || BOOST_MSVC == 1200 || _MSC_FULL_VER > 13102196 # if !defined(BOOST_MSVC) || BOOST_MSVC < 1300 || _MSC_FULL_VER > 13102196
template <class T> template <class T>
inline void force_instantiate(T const&) {} inline void force_instantiate(T const&) {}

View File

@@ -1,62 +1,13 @@
// Copyright David Abrahams 2003. // Copyright David Abrahams 2005.
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#ifndef IS_XXX_DWA2003224_HPP #ifndef IS_XXX_DWA2003224_HPP
# define IS_XXX_DWA2003224_HPP # define IS_XXX_DWA2003224_HPP
# include <boost/config.hpp> # include <boost/detail/is_xxx.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params.hpp>
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) # define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
# include <boost/type_traits/is_reference.hpp> BOOST_DETAIL_IS_XXX_DEF(name, qualified_name, nargs)
# include <boost/type_traits/add_reference.hpp>
# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
template <class X_> \
struct is_##name \
{ \
typedef char yes; \
typedef char (&no)[2]; \
\
static typename add_reference<X_>::type dummy; \
\
struct helpers \
{ \
template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class U) > \
static yes test( \
qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, U) >&, int \
); \
\
template <class U> \
static no test(U&, ...); \
}; \
\
BOOST_STATIC_CONSTANT( \
bool, value \
= !is_reference<X_>::value \
& (sizeof(helpers::test(dummy, 0)) == sizeof(yes))); \
\
typedef mpl::bool_<value> type; \
};
# else
# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \
template <class T> \
struct is_##name : mpl::false_ \
{ \
}; \
\
template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class T) > \
struct is_##name< \
qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, T) > \
> \
: mpl::true_ \
{ \
};
# endif
#endif // IS_XXX_DWA2003224_HPP #endif // IS_XXX_DWA2003224_HPP

View File

@@ -22,6 +22,26 @@
#ifdef _DEBUG #ifdef _DEBUG
# ifndef BOOST_DEBUG_PYTHON # ifndef BOOST_DEBUG_PYTHON
# ifdef _MSC_VER
// VC8.0 will complain if system headers are #included both with
// and without _DEBUG defined, so we have to #include all the
// system headers used by pyconfig.h right here.
# include <stddef.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# include <errno.h>
# include <ctype.h>
# include <wchar.h>
# include <basetsd.h>
# include <io.h>
# include <limits.h>
# include <float.h>
# include <string.h>
# include <math.h>
# include <time.h>
# endif
# undef _DEBUG // Don't let Python force the debug library just because we're debugging. # undef _DEBUG // Don't let Python force the debug library just because we're debugging.
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H # define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# endif # endif
@@ -97,7 +117,7 @@ typedef int pid_t;
# define HAVE_LONG_LONG 1 # define HAVE_LONG_LONG 1
# define LONG_LONG long long # define LONG_LONG long long
# endif # endif
# elif defined(__MWERKS__) # elif defined(__MWERKS__)
@@ -143,6 +163,10 @@ typedef int pid_t;
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H #ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H # undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# define _DEBUG # define _DEBUG
# ifdef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST
# endif
#endif #endif
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2 #if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2

View File

@@ -14,14 +14,14 @@ class override;
namespace detail namespace detail
{ {
class BOOST_PYTHON_DECL wrapper_base; class BOOST_PYTHON_DECL_FORWARD wrapper_base;
namespace wrapper_base_ // ADL disabler namespace wrapper_base_ // ADL disabler
{ {
inline PyObject* get_owner(wrapper_base const volatile& w); inline PyObject* get_owner(wrapper_base const volatile& w);
inline PyObject* inline PyObject*
owner_impl(void const volatile* x, mpl::false_) owner_impl(void const volatile* /*x*/, mpl::false_)
{ {
return 0; return 0;
} }
@@ -79,7 +79,7 @@ namespace detail
w->m_self = self; w->m_self = self;
} }
inline void initialize_wrapper(PyObject* self, ...) {} inline void initialize_wrapper(PyObject* /*self*/, ...) {}

View File

@@ -0,0 +1,76 @@
// Copyright Ralf W. Grosse-Kunstleve 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)
#ifndef DOCSTRING_OPTIONS_RWGK20060111_HPP
# define DOCSTRING_OPTIONS_RWGK20060111_HPP
#include <boost/python/object/function.hpp>
namespace boost { namespace python {
// Note: the static data members are defined in object/function.cpp
class BOOST_PYTHON_DECL docstring_options : boost::noncopyable
{
public:
docstring_options(bool show_all=true)
{
previous_show_user_defined_ = show_user_defined_;
previous_show_signatures_ = show_signatures_;
show_user_defined_ = show_all;
show_signatures_ = show_all;
}
docstring_options(bool show_user_defined, bool show_signatures)
{
previous_show_user_defined_ = show_user_defined_;
previous_show_signatures_ = show_signatures_;
show_user_defined_ = show_user_defined;
show_signatures_ = show_signatures;
}
~docstring_options()
{
show_user_defined_ = previous_show_user_defined_;
show_signatures_ = previous_show_signatures_;
}
void
disable_user_defined() { show_user_defined_ = false; }
void
enable_user_defined() { show_user_defined_ = true; }
void
disable_signatures() { show_signatures_ = false; }
void
enable_signatures() { show_signatures_ = true; }
void
disable_all()
{
show_user_defined_ = false;
show_signatures_ = false;
}
void
enable_all()
{
show_user_defined_ = true;
show_signatures_ = true;
}
friend class objects::function;
private:
static volatile bool show_user_defined_;
static volatile bool show_signatures_;
bool previous_show_user_defined_;
bool previous_show_signatures_;
};
}} // namespace boost::python
#endif // DOCSTRING_OPTIONS_RWGK20060111_HPP

View File

@@ -0,0 +1,31 @@
// Copyright Stefan Seefeld 2005.
// 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)
#ifndef EXEC_SS20050616_HPP
# define EXEC_SS20050616_HPP
# include <boost/python/object.hpp>
# include <boost/python/str.hpp>
namespace boost
{
namespace python
{
// Execute python source code from str.
// global and local are the global and local scopes respectively,
// used during execution.
object
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
exec_file(str filename, object global = object(), object local = object());
}
}
#endif

View File

@@ -22,6 +22,13 @@
# include <boost/utility.hpp> # include <boost/utility.hpp>
# include <boost/call_traits.hpp> # include <boost/call_traits.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
// workaround for VC++ 6.x or 7.0
# define BOOST_EXTRACT_WORKAROUND ()
#else
# define BOOST_EXTRACT_WORKAROUND
#endif
namespace boost { namespace python { namespace boost { namespace python {
namespace api namespace api

View File

@@ -87,7 +87,7 @@ class handle
return *this; return *this;
} }
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
template<typename Y> template<typename Y>
handle& operator=(handle<Y> const & r) // never throws handle& operator=(handle<Y> const & r) // never throws

View File

@@ -0,0 +1,22 @@
// Copyright Stefan Seefeld 2005.
// 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)
#ifndef IMPORT_SS20050624_HPP
# define IMPORT_SS20050624_HPP
# include <boost/python/object.hpp>
# include <boost/python/str.hpp>
namespace boost
{
namespace python
{
// Import the named module and return a reference to it.
object import(str name);
}
}
#endif

View File

@@ -42,7 +42,7 @@ extern "C" \
} \ } \
void init_module_##name() void init_module_##name()
# elif (defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >=5) # elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
# define BOOST_PYTHON_MODULE_INIT(name) \ # define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \ void init_module_##name(); \

View File

@@ -13,4 +13,15 @@
# include <boost/python/object_operators.hpp> # include <boost/python/object_operators.hpp>
# include <boost/python/converter/arg_to_python.hpp> # include <boost/python/converter/arg_to_python.hpp>
namespace boost { namespace python {
inline long len(object const& obj)
{
long result = PyObject_Length(obj.ptr());
if (PyErr_Occurred()) throw_error_already_set();
return result;
}
}} // namespace boost::python
#endif // OBJECT_DWA2002612_HPP #endif // OBJECT_DWA2002612_HPP

View File

@@ -30,6 +30,10 @@
# include <boost/mpl/for_each.hpp> # include <boost/mpl/for_each.hpp>
# include <boost/mpl/placeholders.hpp> # include <boost/mpl/placeholders.hpp>
# include <boost/mpl/single_view.hpp> # include <boost/mpl/single_view.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_convertible.hpp> # include <boost/type_traits/is_convertible.hpp>
# include <boost/noncopyable.hpp> # include <boost/noncopyable.hpp>
@@ -49,6 +53,12 @@ struct register_base_of
template <class Base> template <class Base>
inline void operator()(Base*) const inline void operator()(Base*) const
{ {
# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
# else
BOOST_STATIC_ASSERT(!(is_same<Base,Derived>::value));
# endif
// Register the Base class // Register the Base class
register_dynamic_id<Base>(); register_dynamic_id<Base>();
@@ -58,7 +68,7 @@ struct register_base_of
// Register the down-cast, if appropriate. // Register the down-cast, if appropriate.
this->register_downcast((Base*)0, is_polymorphic<Base>()); this->register_downcast((Base*)0, is_polymorphic<Base>());
} }
private: private:
static inline void register_downcast(void*, mpl::false_) {} static inline void register_downcast(void*, mpl::false_) {}
@@ -186,7 +196,7 @@ struct class_metadata
, mpl::if_< , mpl::if_<
use_value_holder use_value_holder
, value_holder<T> , value_holder<T>
, pointer_holder<held_type,T> , pointer_holder<held_type,wrapped>
> >
>::type holder; >::type holder;
@@ -199,7 +209,8 @@ struct class_metadata
template <class T2> template <class T2>
inline static void register_aux(python::wrapper<T2>*) inline static void register_aux(python::wrapper<T2>*)
{ {
class_metadata::register_aux2((T2*)0, mpl::true_()); typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
class_metadata::register_aux2((T2*)0, use_callback());
} }
inline static void register_aux(void*) inline static void register_aux(void*)
@@ -242,6 +253,7 @@ struct class_metadata
// //
inline static void maybe_register_class_to_python(void*, mpl::true_) {} inline static void maybe_register_class_to_python(void*, mpl::true_) {}
template <class T2> template <class T2>
inline static void maybe_register_class_to_python(T2*, mpl::false_) inline static void maybe_register_class_to_python(T2*, mpl::false_)
{ {

View File

@@ -12,7 +12,7 @@
# include <boost/ref.hpp> # include <boost/ref.hpp>
# include <boost/python/detail/value_arg.hpp> # include <boost/python/detail/value_arg.hpp>
# include <boost/python/detail/copy_ctor_mutates_rhs.hpp> # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
# include <boost/type_traits/is_enum.hpp> # include <boost/type_traits/is_enum.hpp>
# include <boost/mpl/and.hpp> # include <boost/mpl/and.hpp>
# include <boost/mpl/not.hpp> # include <boost/mpl/not.hpp>
@@ -42,7 +42,7 @@ struct reference_to_value
template <class T> template <class T>
struct forward struct forward
: mpl::if_< : mpl::if_<
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// vc6 chokes on unforwarding enums nested in classes // vc6 chokes on unforwarding enums nested in classes
mpl::and_< mpl::and_<
is_scalar<T> is_scalar<T>

View File

@@ -40,6 +40,8 @@ struct BOOST_PYTHON_DECL function : PyObject
object const& name() const; object const& name() const;
private: // helper functions private: // helper functions
object signature(bool show_return_type=false) const;
object signatures(bool show_return_type=false) const;
void argument_error(PyObject* args, PyObject* keywords) const; void argument_error(PyObject* args, PyObject* keywords) const;
void add_overload(handle<function> const&); void add_overload(handle<function> const&);

View File

@@ -177,7 +177,7 @@ namespace detail
inline object make_iterator_function( inline object make_iterator_function(
Accessor1 const& get_start Accessor1 const& get_start
, Accessor2 const& get_finish , Accessor2 const& get_finish
, NextPolicies const& next_policies , NextPolicies const& /*next_policies*/
, Iterator const& (*)() , Iterator const& (*)()
, boost::type<Target>* , boost::type<Target>*
, int , int

View File

@@ -54,8 +54,8 @@ namespace detail {
register_( register_(
Class_& cl, Class_& cl,
tuple (*getinitargs_fn)(Tgetinitargs), tuple (*getinitargs_fn)(Tgetinitargs),
inaccessible* (*getstate_fn)(), inaccessible* (* /*getstate_fn*/)(),
inaccessible* (*setstate_fn)(), inaccessible* (* /*setstate_fn*/)(),
bool) bool)
{ {
cl.enable_pickling_(false); cl.enable_pickling_(false);
@@ -69,7 +69,7 @@ namespace detail {
void void
register_( register_(
Class_& cl, Class_& cl,
inaccessible* (*getinitargs_fn)(), inaccessible* (* /*getinitargs_fn*/)(),
Rgetstate (*getstate_fn)(Tgetstate), Rgetstate (*getstate_fn)(Tgetstate),
void (*setstate_fn)(Tsetstate, Ttuple), void (*setstate_fn)(Tsetstate, Ttuple),
bool getstate_manages_dict) bool getstate_manages_dict)

View File

@@ -0,0 +1,27 @@
// Copyright Eric Niebler 2005.
// 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)
#ifndef STL_ITERATOR_CORE_EAN20051028_HPP
# define STL_ITERATOR_CORE_EAN20051028_HPP
# include <boost/python/object_fwd.hpp>
# include <boost/python/handle_fwd.hpp>
namespace boost { namespace python { namespace objects {
struct BOOST_PYTHON_DECL stl_input_iterator_impl
{
stl_input_iterator_impl();
stl_input_iterator_impl(boost::python::object const &ob);
void increment();
bool equal(stl_input_iterator_impl const &that) const;
boost::python::handle<> const &current() const;
private:
boost::python::object it_;
boost::python::handle<> ob_;
};
}}} // namespace boost::python::object
#endif // STL_ITERATOR_CORE_EAN20051028_HPP

View File

@@ -29,6 +29,8 @@
# include <boost/preprocessor/repetition/enum_params.hpp> # include <boost/preprocessor/repetition/enum_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp> # include <boost/preprocessor/repetition/enum_binary_params.hpp>
# include <boost/utility/addressof.hpp>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
# if BOOST_WORKAROUND(__GNUC__, == 2) # if BOOST_WORKAROUND(__GNUC__, == 2)
@@ -84,19 +86,19 @@ private: // required holder implementation
# undef BOOST_PYTHON_UNFORWARD_LOCAL # undef BOOST_PYTHON_UNFORWARD_LOCAL
template <class Value> template <class Value>
void* value_holder<Value>::holds(type_info dst_t, bool null_ptr_only) void* value_holder<Value>::holds(type_info dst_t, bool /*null_ptr_only*/)
{ {
if (void* wrapped = holds_wrapped(dst_t, &m_held, &m_held)) if (void* wrapped = holds_wrapped(dst_t, boost::addressof(m_held), boost::addressof(m_held)))
return wrapped; return wrapped;
type_info src_t = python::type_id<Value>(); type_info src_t = python::type_id<Value>();
return src_t == dst_t ? &m_held return src_t == dst_t ? boost::addressof(m_held)
: find_static_type(&m_held, src_t, dst_t); : find_static_type(boost::addressof(m_held), src_t, dst_t);
} }
template <class Value, class Held> template <class Value, class Held>
void* value_holder_back_reference<Value,Held>::holds( void* value_holder_back_reference<Value,Held>::holds(
type_info dst_t, bool null_ptr_only) type_info dst_t, bool /*null_ptr_only*/)
{ {
type_info src_t = python::type_id<Value>(); type_info src_t = python::type_id<Value>();
Value* x = &m_held; Value* x = &m_held;
@@ -132,7 +134,7 @@ void* value_holder_back_reference<Value,Held>::holds(
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
) )
{ {
python::detail::initialize_wrapper(self, &this->m_held); python::detail::initialize_wrapper(self, boost::addressof(this->m_held));
} }
# undef N # undef N

View File

@@ -86,7 +86,7 @@ namespace api
class object_operators : public def_visitor<U> class object_operators : public def_visitor<U>
{ {
protected: protected:
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 # if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
typedef object const& object_cref; typedef object const& object_cref;
# else # else
typedef object object_cref; typedef object object_cref;
@@ -300,7 +300,7 @@ namespace api
template <class T> template <class T>
explicit object( explicit object(
T const& x T const& x
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// use some SFINAE to un-confuse MSVC about its // use some SFINAE to un-confuse MSVC about its
// copy-initialization ambiguity claim. // copy-initialization ambiguity claim.
, typename mpl::if_<is_proxy<T>,int&,int>::type* = 0 , typename mpl::if_<is_proxy<T>,int&,int>::type* = 0
@@ -331,7 +331,7 @@ namespace api
inline explicit derived(python::detail::new_non_null_reference p) \ inline explicit derived(python::detail::new_non_null_reference p) \
: base(p) {} : base(p) {}
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 # if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_ # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_
# else # else
// MSVC6 has a bug which causes an explicit template constructor to // MSVC6 has a bug which causes an explicit template constructor to

View File

@@ -13,15 +13,22 @@
# include <boost/python/to_python_converter.hpp> # include <boost/python/to_python_converter.hpp>
# include <boost/python/detail/dealloc.hpp> # include <boost/python/detail/dealloc.hpp>
# include <boost/python/detail/none.hpp> # include <boost/python/detail/none.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/errors.hpp>
# include <boost/type_traits/remove_pointer.hpp> # include <boost/type_traits/remove_pointer.hpp>
# include <boost/type_traits/is_pointer.hpp> # include <boost/type_traits/is_pointer.hpp>
# include <boost/type_traits/is_void.hpp>
// opaque_pointer_converter -- # include <boost/implicit_cast.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/assert.hpp>
// opaque --
// //
// usage: opaque_pointer_converter<Pointer>("name") // registers to- and from- python conversions for a type Pointee.
//
// registers to- and from- python conversions for a type Pointer,
// and a corresponding Python type called "name".
// //
// Note: // Note:
// In addition you need to define specializations for type_id // In addition you need to define specializations for type_id
@@ -31,92 +38,120 @@
// For an example see libs/python/test/opaque.cpp // For an example see libs/python/test/opaque.cpp
// //
namespace boost { namespace python { namespace boost { namespace python {
namespace detail {
template <class R>
struct opaque_pointer_converter_requires_a_pointer_type
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
{}
# endif
;
}
template <class Pointer> template <class Pointee>
struct opaque_pointer_converter struct opaque
: to_python_converter<
Pointer, opaque_pointer_converter<Pointer> >
{ {
BOOST_STATIC_CONSTANT( opaque()
bool, ok = is_pointer<Pointer>::value);
typedef typename mpl::if_c<
ok
, Pointer
, detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
>::type ptr_type;
private:
struct instance;
public:
explicit opaque_pointer_converter(char const* name)
{ {
type_object.tp_name = const_cast<char *> (name); type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name());
converter::registry::insert(&extract, type_id<Pointee>());
lvalue_from_pytype< converter::registry::insert(&wrap, type_id<Pointee*>());
opaque_pointer_converter<ptr_type>, }
&opaque_pointer_converter<ptr_type>::type_object
>(); static opaque instance;
private:
static void* extract(PyObject* op)
{
return PyObject_TypeCheck(op, &type_object)
? static_cast<python_instance*>(implicit_cast<void*>(op))->x
: 0
;
} }
static PyObject* convert(ptr_type x) static PyObject* wrap(void const* px)
{ {
PyObject *result = 0; Pointee* x = *static_cast<Pointee*const*>(px);
if (x != 0) { if (x == 0)
instance *o = PyObject_New (instance, &type_object); return detail::none();
o->x = x; if ( python_instance *o = PyObject_New(python_instance, &type_object) )
result = &o->base_; {
} else { o->x = x;
result = detail::none(); return static_cast<PyObject*>(implicit_cast<void*>(o));
}
else
{
throw error_already_set();
} }
return (result);
} }
static typename ::boost::remove_pointer<ptr_type>::type& struct python_instance
execute(instance &p_)
{ {
return *p_.x; PyObject_HEAD
} Pointee* x;
private:
static PyTypeObject type_object;
// This is a POD so we can use PyObject_Del on it, for example.
struct instance
{
PyObject base_;
ptr_type x;
}; };
static PyTypeObject type_object;
}; };
template <class Pointer> template <class Pointee>
PyTypeObject opaque_pointer_converter<Pointer>::type_object = opaque<Pointee> opaque<Pointee>::instance;
template <class Pointee>
PyTypeObject opaque<Pointee>::type_object =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(0)
0, 0,
0, 0,
sizeof(typename opaque_pointer_converter<Pointer>::instance), sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
0, 0,
::boost::python::detail::dealloc ::boost::python::detail::dealloc,
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
}} // namespace boost::python }} // namespace boost::python
# ifdef BOOST_MSVC
// MSC works without this workaround, but needs another one ... # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee) # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
# else # else
// If you change the below, don't forget to alter the end of type_id.hpp
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
namespace boost { namespace python { \ namespace boost { namespace python { \
template<> \ template<> \
@@ -130,6 +165,8 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
{ \ { \
return type_info (typeid (Pointee *)); \ return type_info (typeid (Pointee *)); \
} \ } \
}} }}
# endif # endif
# endif // OPAQUE_POINTER_CONVERTER_HPP_ # endif // OPAQUE_POINTER_CONVERTER_HPP_

View File

@@ -55,12 +55,15 @@ namespace detail
} }
# endif # endif
# if !defined(BOOST_MSVC) || BOOST_WORKAROUND(_MSC_FULL_VER, > 140040607) # if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) || BOOST_WORKAROUND(BOOST_INTEL_WIN, >= 900)
// No operator T&
# else
template <class T> template <class T>
operator T&() const operator T&() const
{ {
converter::return_from_python<T&> converter; converter::return_from_python<T&> converter;
return converter(m_obj.release()); return converter(const_cast<handle<>&>(m_obj).release());
} }
# endif # endif

View File

@@ -15,7 +15,7 @@ class proxy : public object_operators<proxy<Policies> >
{ {
typedef typename Policies::key_type key_type; typedef typename Policies::key_type key_type;
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 # if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
typedef proxy const& assignment_self; typedef proxy const& assignment_self;
# else # else
typedef proxy assignment_self; typedef proxy assignment_self;

View File

@@ -70,10 +70,8 @@ namespace detail
: m_pmf(pmf) : m_pmf(pmf)
{} {}
#if !BOOST_WORKAROUND(__EDG_VERSION__, <= 245)
private: private:
#endif friend class python::def_visitor_access;
friend class def_visitor_access;
template <class C_, class Options> template <class C_, class Options>
void visit(C_& c, char const* name, Options& options) const void visit(C_& c, char const* name, Options& options) const

View File

@@ -10,47 +10,38 @@
# include <boost/python/detail/prefix.hpp> # include <boost/python/detail/prefix.hpp>
# include <boost/python/opaque_pointer_converter.hpp> # include <boost/python/opaque_pointer_converter.hpp>
# include <boost/python/detail/indirect_traits.hpp> # include <boost/python/detail/force_instantiate.hpp>
# include <boost/mpl/if.hpp> # include <boost/python/to_python_value.hpp>
# include <boost/python/detail/value_arg.hpp>
# include <boost/mpl/assert.hpp>
namespace boost { namespace python { namespace boost { namespace python {
namespace detail namespace detail
{ {
template <class Pointer> template <class Pointee>
struct opaque_conversion_holder static void opaque_pointee(Pointee const volatile*)
{ {
inline PyObject *operator()(Pointer p) const force_instantiate(opaque<Pointee>::instance);
{ }
static opaque_pointer_converter<Pointer> converter (
typeid (Pointer).name());
return converter.convert(p);
}
};
template <class R>
struct return_opaque_pointer_requires_a_pointer_type
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
{}
# endif
;
} }
struct return_opaque_pointer struct return_opaque_pointer
{ {
template <class R> template <class R>
struct apply struct apply
{ {
BOOST_STATIC_CONSTANT( BOOST_MPL_ASSERT_MSG( is_pointer<R>::value, RETURN_OPAQUE_POINTER_EXPECTS_A_POINTER_TYPE, (R));
bool, ok = is_pointer<R>::value);
typedef typename mpl::if_c< struct type :
ok boost::python::to_python_value<
, detail::opaque_conversion_holder<R> typename detail::value_arg<R>::type
, detail::return_opaque_pointer_requires_a_pointer_type<R> >
>::type type; {
type() { detail::opaque_pointee(R()); }
};
}; };
}; };
}} // namespace boost::python }} // namespace boost::python
# endif // RETURN_OPAQUE_POINTER_HPP_ # endif // RETURN_OPAQUE_POINTER_HPP_

View File

@@ -0,0 +1,61 @@
// Copyright Eric Niebler 2005.
// 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)
#ifndef STL_ITERATOR_EAN20051028_HPP
# define STL_ITERATOR_EAN20051028_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/object/stl_iterator_core.hpp>
# include <boost/iterator/iterator_facade.hpp>
namespace boost { namespace python
{
// An STL input iterator over a python sequence
template<typename ValueT>
struct stl_input_iterator
: boost::iterator_facade<
stl_input_iterator<ValueT>
, ValueT
, std::input_iterator_tag
, ValueT
>
{
stl_input_iterator()
: impl_()
{
}
// ob is the python sequence
stl_input_iterator(boost::python::object const &ob)
: impl_(ob)
{
}
private:
friend class boost::iterator_core_access;
void increment()
{
this->impl_.increment();
}
ValueT dereference() const
{
return extract<ValueT>(this->impl_.current().get())();
}
bool equal(stl_input_iterator<ValueT> const &that) const
{
return this->impl_.equal(that.impl_);
}
objects::stl_input_iterator_impl impl_;
};
}} // namespace boost::python
#endif // STL_ITERATOR_EAN20051028_HPP

View File

@@ -490,20 +490,20 @@ namespace boost { namespace python { namespace detail {
static void static void
base_replace_indexes( base_replace_indexes(
Container& container, Index from, Container& /*container*/, Index /*from*/,
Index to, Index n) Index /*to*/, Index /*n*/)
{ {
} }
template <class NoSlice> template <class NoSlice>
static void static void
base_erase_index( base_erase_index(
Container& container, Index i, NoSlice no_slice) Container& /*container*/, Index /*i*/, NoSlice /*no_slice*/)
{ {
} }
static void static void
base_erase_indexes(Container& container, Index from, Index to) base_erase_indexes(Container& /*container*/, Index /*from*/, Index /*to*/)
{ {
} }
}; };
@@ -715,20 +715,20 @@ namespace boost { namespace python { namespace detail {
} }
static object static object
base_get_slice(Container& container, PySliceObject* slice) base_get_slice(Container& /*container*/, PySliceObject* /*slice*/)
{ {
slicing_not_suported(); slicing_not_suported();
return object(); return object();
} }
static void static void
base_set_slice(Container& container, PySliceObject* slice, PyObject* v) base_set_slice(Container& /*container*/, PySliceObject* /*slice*/, PyObject* /*v*/)
{ {
slicing_not_suported(); slicing_not_suported();
} }
static void static void
base_delete_slice(Container& container, PySliceObject* slice) base_delete_slice(Container& /*container*/, PySliceObject* /*slice*/)
{ {
slicing_not_suported(); slicing_not_suported();
} }

View File

@@ -14,6 +14,7 @@
# include <boost/python/iterator.hpp> # include <boost/python/iterator.hpp>
# include <boost/mpl/or.hpp> # include <boost/mpl/or.hpp>
# include <boost/mpl/not.hpp> # include <boost/mpl/not.hpp>
# include <boost/type_traits/is_same.hpp>
namespace boost { namespace python { namespace boost { namespace python {
@@ -119,13 +120,18 @@ namespace boost { namespace python {
typedef mpl::or_< typedef mpl::or_<
mpl::bool_<NoProxy> mpl::bool_<NoProxy>
, mpl::not_<is_class<Data> > > , mpl::not_<is_class<Data> >
, typename mpl::or_<
is_same<Data, std::string>
, is_same<Data, std::complex<float> >
, is_same<Data, std::complex<double> >
, is_same<Data, std::complex<long double> > >::type>
no_proxy; no_proxy;
typedef detail::container_element<Container, Index, DerivedPolicies> typedef detail::container_element<Container, Index, DerivedPolicies>
container_element_t; container_element_t;
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
struct return_policy : return_internal_reference<> {}; struct return_policy : return_internal_reference<> {};
#else #else
typedef return_internal_reference<> return_policy; typedef return_internal_reference<> return_policy;

View File

@@ -26,7 +26,7 @@ namespace boost { namespace python {
} }
// The map_indexing_suite class is a predefined indexing_suite derived // The map_indexing_suite class is a predefined indexing_suite derived
// class for wrapping std::vector (and std::vector like) classes. It provides // class for wrapping std::map (and std::map like) classes. It provides
// all the policies required by the indexing_suite (see indexing_suite). // all the policies required by the indexing_suite (see indexing_suite).
// Example usage: // Example usage:
// //
@@ -78,7 +78,7 @@ namespace boost { namespace python {
elem_name += "_entry"; elem_name += "_entry";
typedef typename mpl::if_< typedef typename mpl::if_<
is_class<data_type> mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> >
, return_internal_reference<> , return_internal_reference<>
, default_call_policies , default_call_policies
>::type get_data_return_policy; >::type get_data_return_policy;
@@ -98,7 +98,7 @@ namespace boost { namespace python {
static static
typename mpl::if_< typename mpl::if_<
is_class<data_type> mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> >
, data_type& , data_type&
, data_type , data_type
>::type >::type
@@ -156,7 +156,7 @@ namespace boost { namespace python {
} }
static index_type static index_type
convert_index(Container& container, PyObject* i_) convert_index(Container& /*container*/, PyObject* i_)
{ {
extract<key_type const&> i(i_); extract<key_type const&> i(i_);
if (i.check()) if (i.check())

View File

@@ -148,7 +148,7 @@ namespace boost { namespace python {
} }
static index_type static index_type
get_min_index(Container& container) get_min_index(Container& /*container*/)
{ {
return 0; return 0;
} }
@@ -160,7 +160,7 @@ namespace boost { namespace python {
} }
static bool static bool
compare_index(Container& container, index_type a, index_type b) compare_index(Container& /*container*/, index_type a, index_type b)
{ {
return a < b; return a < b;
} }

View File

@@ -14,6 +14,7 @@
# include <boost/static_assert.hpp> # include <boost/static_assert.hpp>
# include <boost/detail/workaround.hpp> # include <boost/detail/workaround.hpp>
# include <boost/type_traits/same_traits.hpp> # include <boost/type_traits/same_traits.hpp>
# include <boost/type_traits/broken_compiler_spec.hpp>
# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE # ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__GNUC__) \ # if defined(__GNUC__) \
@@ -35,6 +36,13 @@ namespace boost { namespace python {
# define BOOST_PYTHON_TYPE_ID_NAME # define BOOST_PYTHON_TYPE_ID_NAME
# endif # endif
#ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
// Runtime detection of broken cxxabi::__cxa_demangle versions,
// to avoid #ifdef clutter.
bool cxxabi_cxa_demangle_is_broken();
#define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN
#endif
// type ids which represent the same information as std::type_info // type ids which represent the same information as std::type_info
// (i.e. the top-level reference and cv-qualifiers are stripped), but // (i.e. the top-level reference and cv-qualifiers are stripped), but
// which works across shared libraries. // which works across shared libraries.
@@ -161,6 +169,22 @@ inline char const* type_info::name() const
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&);
# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template<>
inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void))
{
return type_info (typeid (void *));
}
# ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template<>
inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void))
{
return type_info (typeid (void *));
}
# endif
# endif
}} // namespace boost::python }} // namespace boost::python
#endif // TYPE_ID_DWA2002517_HPP #endif // TYPE_ID_DWA2002517_HPP

View File

@@ -84,7 +84,14 @@ struct with_custodian_and_ward_postcall : BasePolicy_
static PyObject* postcall(ArgumentPackage const& args_, PyObject* result) static PyObject* postcall(ArgumentPackage const& args_, PyObject* result)
{ {
std::size_t arity_ = detail::arity(args_); std::size_t arity_ = detail::arity(args_);
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
if ( custodian > arity_ || ward > arity_ ) if ( custodian > arity_ || ward > arity_ )
#else
// check if either custodian or ward exceeds the arity
// (this weird formulation avoids "always false" warnings
// for arity_ = 0)
if ( std::max(custodian, ward) > arity_ )
#endif
{ {
PyErr_SetString( PyErr_SetString(
PyExc_IndexError PyExc_IndexError

View File

@@ -278,6 +278,7 @@ namespace
} }
}; };
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
// encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc // encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc
// "slot" which encodes a Python string using the default encoding // "slot" which encodes a Python string using the default encoding
extern "C" PyObject* encode_string_unaryfunc(PyObject* x) extern "C" PyObject* encode_string_unaryfunc(PyObject* x)
@@ -286,8 +287,6 @@ namespace
} }
unaryfunc py_encode_string = encode_string_unaryfunc; unaryfunc py_encode_string = encode_string_unaryfunc;
#ifndef BOOST_NO_STD_WSTRING
// A SlotPolicy for extracting C++ strings from Python objects. // A SlotPolicy for extracting C++ strings from Python objects.
struct wstring_rvalue_from_python struct wstring_rvalue_from_python
{ {
@@ -411,8 +410,8 @@ void initialize_builtin_converters()
// Add an lvalue converter for char which gets us char const* // Add an lvalue converter for char which gets us char const*
registry::insert(convert_to_cstring,type_id<char>()); registry::insert(convert_to_cstring,type_id<char>());
# ifndef BOOST_NO_STD_WSTRING
// Register by-value converters to std::string, std::wstring // Register by-value converters to std::string, std::wstring
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>(); slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
# endif # endif
slot_rvalue_from_python<std::string, string_rvalue_from_python>(); slot_rvalue_from_python<std::string, string_rvalue_from_python>();

View File

@@ -18,9 +18,16 @@
# include <ostream.h> # include <ostream.h>
#endif #endif
# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__GNUC__) && __GNUC__ >= 3 # if defined(__GNUC__) && __GNUC__ >= 3
// http://lists.debian.org/debian-gcc/2003/09/msg00055.html notes
// that, in cxxabi.h of gcc-3.x for x < 4, this type is used before it
// is declared.
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
class __class_type_info;
# endif
# include <cxxabi.h> # include <cxxabi.h>
# endif # endif
# endif # endif
@@ -70,6 +77,21 @@ namespace
}; };
} }
bool cxxabi_cxa_demangle_is_broken()
{
static bool was_tested = false;
static bool is_broken = false;
if (!was_tested) {
int status;
free_mem keeper(cxxabi::__cxa_demangle("b", 0, 0, &status));
was_tested = true;
if (status == -2 || strcmp(keeper.p, "bool") != 0) {
is_broken = true;
}
}
return is_broken;
}
namespace detail namespace detail
{ {
BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled) BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled)
@@ -107,6 +129,44 @@ namespace detail
? mangled ? mangled
: keeper.p; : keeper.p;
// Ult Mundane, 2005 Aug 17
// Contributed 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)
// The __cxa_demangle function is supposed to translate
// builtin types from their one-character mangled names,
// but it doesn't in gcc 3.3.5 and gcc 3.4.x.
if (cxxabi_cxa_demangle_is_broken()
&& status == -2 && strlen(mangled) == 1)
{
// list from
// http://www.codesourcery.com/cxx-abi/abi.html
switch (mangled[0])
{
case 'v': demangled = "void"; break;
case 'w': demangled = "wchar_t"; break;
case 'b': demangled = "bool"; break;
case 'c': demangled = "char"; break;
case 'a': demangled = "signed char"; break;
case 'h': demangled = "unsigned char"; break;
case 's': demangled = "short"; break;
case 't': demangled = "unsigned short"; break;
case 'i': demangled = "int"; break;
case 'j': demangled = "unsigned int"; break;
case 'l': demangled = "long"; break;
case 'm': demangled = "unsigned long"; break;
case 'x': demangled = "long long"; break;
case 'y': demangled = "unsigned long long"; break;
case 'n': demangled = "__int128"; break;
case 'o': demangled = "unsigned __int128"; break;
case 'f': demangled = "float"; break;
case 'd': demangled = "double"; break;
case 'e': demangled = "long double"; break;
case 'g': demangled = "__float128"; break;
case 'z': demangled = "..."; break;
}
}
p = demangler.insert(p, std::make_pair(mangled, demangled)); p = demangler.insert(p, std::make_pair(mangled, demangled));
keeper.p = 0; keeper.p = 0;
} }

45
src/exec.cpp Normal file
View File

@@ -0,0 +1,45 @@
// Copyright Stefan Seefeld 2005.
// 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)
#include <boost/python/exec.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/handle.hpp>
namespace boost
{
namespace python
{
object exec(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_file_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
// Execute python source code from file filename.
// global and local are the global and local scopes respectively,
// used during execution.
object exec_file(str filename, object global, object local)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *f = python::extract<char *>(filename);
// Let python open the file to avoid potential binary incompatibilities.
PyObject *pyfile = PyFile_FromString(f, "r");
if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file");
python::handle<> file(pyfile);
PyObject* result = PyRun_File(PyFile_AsFile(file.get()),
f,
Py_file_input,
global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
} // namespace boost::python
} // namespace boost

25
src/import.cpp Normal file
View File

@@ -0,0 +1,25 @@
// Copyright Stefan Seefeld 2005.
// 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)
#include <boost/python/import.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/handle.hpp>
namespace boost
{
namespace python
{
object import(str name)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *n = python::extract<char *>(name);
python::handle<> module(python::borrowed(PyImport_AddModule(n)));
return python::object(module);
}
} // namespace boost::python
} // namespace boost

View File

@@ -69,7 +69,7 @@ extern "C"
} propertyobject; } propertyobject;
static PyObject * static PyObject *
static_data_descr_get(PyObject *self, PyObject *obj, PyObject * /*type*/) static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
{ {
propertyobject *gs = (propertyobject *)self; propertyobject *gs = (propertyobject *)self;
@@ -77,7 +77,7 @@ extern "C"
} }
static int static int
static_data_descr_set(PyObject *self, PyObject *obj, PyObject *value) static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
{ {
propertyobject *gs = (propertyobject *)self; propertyobject *gs = (propertyobject *)self;
PyObject *func, *res; PyObject *func, *res;
@@ -147,6 +147,14 @@ static PyTypeObject static_data_object = {
0, // filled in with type_new /* tp_new */ 0, // filled in with type_new /* tp_new */
0, // filled in with __PyObject_GC_Del /* tp_free */ 0, // filled in with __PyObject_GC_Del /* tp_free */
(inquiry)type_is_gc, /* tp_is_gc */ (inquiry)type_is_gc, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
namespace objects namespace objects
@@ -243,6 +251,14 @@ static PyTypeObject class_metatype_object = {
0, // filled in with type_new /* tp_new */ 0, // filled in with type_new /* tp_new */
0, // filled in with __PyObject_GC_Del /* tp_free */ 0, // filled in with __PyObject_GC_Del /* tp_free */
(inquiry)type_is_gc, /* tp_is_gc */ (inquiry)type_is_gc, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
// Install the instance data for a C++ object into a Python instance // Install the instance data for a C++ object into a Python instance
@@ -295,7 +311,7 @@ namespace objects
} }
static PyObject * static PyObject *
instance_new(PyTypeObject* type_, PyObject* args, PyObject *kw) instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
{ {
// Attempt to find the __instance_size__ attribute. If not present, no problem. // Attempt to find the __instance_size__ attribute. If not present, no problem.
PyObject* d = type_->tp_dict; PyObject* d = type_->tp_dict;
@@ -340,14 +356,14 @@ namespace objects
static PyGetSetDef instance_getsets[] = { static PyGetSetDef instance_getsets[] = {
{"__dict__", instance_get_dict, instance_set_dict, NULL}, {"__dict__", instance_get_dict, instance_set_dict, NULL, 0},
{0} {0, 0, 0, 0, 0}
}; };
static PyMemberDef instance_members[] = { static PyMemberDef instance_members[] = {
{"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0}, {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
{0} {0, 0, 0, 0, 0}
}; };
static PyTypeObject class_type_object = { static PyTypeObject class_type_object = {
@@ -390,7 +406,17 @@ namespace objects
offsetof(instance<>,dict), /* tp_dictoffset */ offsetof(instance<>,dict), /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
instance_new /* tp_new */ instance_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
BOOST_PYTHON_DECL type_handle class_type() BOOST_PYTHON_DECL type_handle class_type()

View File

@@ -12,9 +12,7 @@
#include <boost/python/str.hpp> #include <boost/python/str.hpp>
#include <boost/python/extract.hpp> #include <boost/python/extract.hpp>
#include <boost/python/object_protocol.hpp> #include <boost/python/object_protocol.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <structmember.h> #include <structmember.h>
#include <cstdio>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
@@ -25,30 +23,13 @@ struct enum_object
}; };
static PyMemberDef enum_members[] = { static PyMemberDef enum_members[] = {
{"name", T_OBJECT_EX, offsetof(enum_object,name),READONLY}, {"name", T_OBJECT_EX, offsetof(enum_object,name),READONLY, 0},
{0} {0, 0, 0, 0, 0}
}; };
extern "C" extern "C"
{ {
static int
enum_print(PyObject *v, BOOST_CSTD_::FILE *fp, int flags)
{
PyObject* s
= (flags & Py_PRINT_RAW) ? v->ob_type->tp_str(v) : v->ob_type->tp_repr(v);
if (s == 0)
return -1;
char const* text = PyString_AsString(s);
if (text == 0)
return -1;
BOOST_CSTD_::fprintf(fp, text);
return 0;
}
/* flags -- not used but required by interface */
static PyObject* enum_repr(PyObject* self_) static PyObject* enum_repr(PyObject* self_)
{ {
enum_object* self = downcast<enum_object>(self_); enum_object* self = downcast<enum_object>(self_);
@@ -87,7 +68,7 @@ static PyTypeObject enum_type_object = {
sizeof(enum_object), /* tp_basicsize */ sizeof(enum_object), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
0, /* tp_dealloc */ 0, /* tp_dealloc */
enum_print, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
@@ -122,7 +103,17 @@ static PyTypeObject enum_type_object = {
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
0 /* tp_new */ 0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
object module_prefix(); object module_prefix();

View File

@@ -3,7 +3,7 @@
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/function.hpp> #include <boost/python/docstring_options.hpp>
#include <boost/python/object/function_object.hpp> #include <boost/python/object/function_object.hpp>
#include <boost/python/object/function_handle.hpp> #include <boost/python/object/function_handle.hpp>
#include <boost/python/errors.hpp> #include <boost/python/errors.hpp>
@@ -15,7 +15,6 @@
#include <boost/python/tuple.hpp> #include <boost/python/tuple.hpp>
#include <boost/python/list.hpp> #include <boost/python/list.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/detail/signature.hpp> #include <boost/python/detail/signature.hpp>
#include <boost/mpl/vector/vector10.hpp> #include <boost/mpl/vector/vector10.hpp>
@@ -28,6 +27,11 @@
# include <cstdio> # include <cstdio>
#endif #endif
namespace boost { namespace python {
volatile bool docstring_options::show_user_defined_ = true;
volatile bool docstring_options::show_signatures_ = true;
}}
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
py_function_impl_base::~py_function_impl_base() py_function_impl_base::~py_function_impl_base()
@@ -228,7 +232,59 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
return 0; return 0;
} }
void function::argument_error(PyObject* args, PyObject* keywords) const object function::signature(bool show_return_type) const
{
py_function const& impl = m_fn;
python::detail::signature_element const* return_type = impl.signature();
python::detail::signature_element const* s = return_type + 1;
list formal_params;
if (impl.max_arity() == 0)
formal_params.append("void");
for (unsigned n = 0; n < impl.max_arity(); ++n)
{
if (s[n].basename == 0)
{
formal_params.append("...");
break;
}
str param(s[n].basename);
if (s[n].lvalue)
param += " {lvalue}";
if (m_arg_names) // None or empty tuple will test false
{
object kv(m_arg_names[n]);
if (kv)
{
char const* const fmt = len(kv) > 1 ? " %s=%r" : " %s";
param += fmt % kv;
}
}
formal_params.append(param);
}
if (show_return_type)
return "%s(%s) -> %s" % make_tuple(
m_name, str(", ").join(formal_params), return_type->basename);
return "%s(%s)" % make_tuple(
m_name, str(", ").join(formal_params));
}
object function::signatures(bool show_return_type) const
{
list result;
for (function const* f = this; f; f = f->m_overloads.get()) {
result.append(f->signature(show_return_type));
}
return result;
}
void function::argument_error(PyObject* args, PyObject* /*keywords*/) const
{ {
static handle<> exception( static handle<> exception(
PyErr_NewException("Boost.Python.ArgumentError", PyExc_TypeError, 0)); PyErr_NewException("Boost.Python.ArgumentError", PyExc_TypeError, 0));
@@ -244,50 +300,7 @@ void function::argument_error(PyObject* args, PyObject* keywords) const
} }
message += str(", ").join(actual_args); message += str(", ").join(actual_args);
message += ")\ndid not match C++ signature:\n "; message += ")\ndid not match C++ signature:\n ";
message += str("\n ").join(signatures());
list signatures;
for (function const* f = this; f; f = f->m_overloads.get())
{
py_function const& impl = f->m_fn;
python::detail::signature_element const* s
= impl.signature() + 1; // skip over return type
list formal_params;
if (impl.max_arity() == 0)
formal_params.append("void");
for (unsigned n = 0; n < impl.max_arity(); ++n)
{
if (s[n].basename == 0)
{
formal_params.append("...");
break;
}
str param(s[n].basename);
if (s[n].lvalue)
param += " {lvalue}";
if (f->m_arg_names) // None or empty tuple will test false
{
object kv(f->m_arg_names[n]);
if (kv)
{
char const* const fmt = len(kv) > 1 ? " %s=%r" : " %s";
param += fmt % kv;
}
}
formal_params.append(param);
}
signatures.append(
"%s(%s)" % make_tuple(f->m_name, str(", ").join(formal_params))
);
}
message += str("\n ").join(signatures);
#if BOOST_PYTHON_DEBUG_ERROR_MESSAGES #if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
std::printf("\n--------\n%s\n--------\n", extract<const char*>(message)()); std::printf("\n--------\n%s\n--------\n", extract<const char*>(message)());
@@ -391,6 +404,12 @@ namespace
void function::add_to_namespace( void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute) object const& name_space, char const* name_, object const& attribute)
{
add_to_namespace(name_space, name_, attribute, 0);
}
void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute, char const* doc)
{ {
str const name(name_); str const name(name_);
PyObject* const ns = name_space.ptr(); PyObject* const ns = name_space.ptr();
@@ -463,16 +482,11 @@ void function::add_to_namespace(
PyErr_Clear(); PyErr_Clear();
if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0)
throw_error_already_set(); throw_error_already_set();
}
void function::add_to_namespace( object mutable_attribute(attribute);
object const& name_space, char const* name_, object const& attribute, char const* doc) if (doc != 0 && docstring_options::show_user_defined_)
{
add_to_namespace(name_space, name_, attribute);
if (doc != 0)
{ {
// Accumulate documentation // Accumulate documentation
object mutable_attribute(attribute);
if ( if (
PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__") PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
@@ -481,21 +495,36 @@ void function::add_to_namespace(
mutable_attribute.attr("__doc__") += "\n\n"; mutable_attribute.attr("__doc__") += "\n\n";
mutable_attribute.attr("__doc__") += doc; mutable_attribute.attr("__doc__") += doc;
} }
else else {
mutable_attribute.attr("__doc__") = doc; mutable_attribute.attr("__doc__") = doc;
}
}
if (docstring_options::show_signatures_)
{
if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
&& mutable_attribute.attr("__doc__")) {
mutable_attribute.attr("__doc__") += "\n";
}
else {
mutable_attribute.attr("__doc__") = "";
}
function* f = downcast<function>(attribute.ptr());
mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple(
"C++ signature:", f->signature(true)));
} }
} }
BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace(
object const& name_space, char const* name, object const& attribute) object const& name_space, char const* name, object const& attribute)
{ {
function::add_to_namespace(name_space, name, attribute); function::add_to_namespace(name_space, name, attribute, 0);
} }
BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace(
object const& name_space, char const* name, object const& attribute, char const* doc) object const& name_space, char const* name, object const& attribute, char const* doc)
{ {
function::add_to_namespace(name_space, name, attribute, doc); function::add_to_namespace(name_space, name, attribute, doc);
} }
@@ -580,19 +609,19 @@ extern "C"
// We add a dummy __class__ attribute in order to fool PyDoc into // We add a dummy __class__ attribute in order to fool PyDoc into
// treating these as built-in functions and scanning their // treating these as built-in functions and scanning their
// documentation // documentation
static PyObject* function_get_class(PyObject* op, void*) static PyObject* function_get_class(PyObject* /*op*/, void*)
{ {
return python::incref(upcast<PyObject>(&PyCFunction_Type)); return python::incref(upcast<PyObject>(&PyCFunction_Type));
} }
} }
static PyGetSetDef function_getsetlist[] = { static PyGetSetDef function_getsetlist[] = {
{"__name__", (getter)function_get_name, 0 }, {"__name__", (getter)function_get_name, 0, 0, 0 },
{"func_name", (getter)function_get_name, 0 }, {"func_name", (getter)function_get_name, 0, 0, 0 },
{"__class__", (getter)function_get_class, 0 }, // see note above {"__class__", (getter)function_get_class, 0, 0, 0 }, // see note above
{"__doc__", (getter)function_get_doc, (setter)function_set_doc}, {"__doc__", (getter)function_get_doc, (setter)function_set_doc, 0, 0},
{"func_doc", (getter)function_get_doc, (setter)function_set_doc}, {"func_doc", (getter)function_get_doc, (setter)function_set_doc, 0, 0},
{NULL} /* Sentinel */ {NULL, 0, 0, 0, 0} /* Sentinel */
}; };
PyTypeObject function_type = { PyTypeObject function_type = {
@@ -634,8 +663,17 @@ PyTypeObject function_type = {
0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */ 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
0, 0, /* tp_new */
0 /* tp_new */ 0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
object function_object( object function_object(

View File

@@ -24,7 +24,7 @@ extern "C"
} }
static PyObject * static PyObject *
life_support_call(PyObject *self, PyObject *arg, PyObject *kw) life_support_call(PyObject *self, PyObject *arg, PyObject * /*kw*/)
{ {
// Let the patient die now // Let the patient die now
Py_XDECREF(((life_support*)self)->patient); Py_XDECREF(((life_support*)self)->patient);
@@ -74,8 +74,17 @@ PyTypeObject life_support_type = {
0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */ 0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
0, 0, /* tp_new */
0 /* tp_new */ 0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
}; };
PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)

View File

@@ -8,7 +8,6 @@
#include <boost/python/tuple.hpp> #include <boost/python/tuple.hpp>
#include <boost/python/list.hpp> #include <boost/python/list.hpp>
#include <boost/python/dict.hpp> #include <boost/python/dict.hpp>
#include <boost/python/detail/api_placeholder.hpp>
namespace boost { namespace python { namespace boost { namespace python {

42
src/object/stl_iterator.cpp Executable file
View File

@@ -0,0 +1,42 @@
// Copyright Eric Niebler 2005.
// 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)
#include <boost/python/object.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/object/stl_iterator_core.hpp>
namespace boost { namespace python { namespace objects
{
stl_input_iterator_impl::stl_input_iterator_impl()
: it_()
, ob_()
{
}
stl_input_iterator_impl::stl_input_iterator_impl(boost::python::object const &ob)
: it_(ob.attr("__iter__")())
, ob_()
{
this->increment();
}
void stl_input_iterator_impl::increment()
{
this->ob_ = boost::python::handle<>(
boost::python::allow_null(PyIter_Next(this->it_.ptr())));
}
bool stl_input_iterator_impl::equal(stl_input_iterator_impl const &that) const
{
return !this->ob_ == !that.ob_;
}
boost::python::handle<> const &stl_input_iterator_impl::current() const
{
return this->ob_;
}
}}} // namespace boost::python::objects

View File

@@ -74,10 +74,10 @@ rule bpl-test ( name ? : files * : requirements * )
test-suite python test-suite python
: :
[ [
run ../test/embedding.cpp <lib>../build/boost_python run ../test/exec.cpp <lib>../build/boost_python
: # program args : # program args
: # input files : exec.py
: # requirements : # requirements
$(PYTHON_PROPERTIES) $(PYTHON_PROPERTIES)
<define>BOOST_PYTHON_STATIC_LIB <define>BOOST_PYTHON_STATIC_LIB
@@ -101,6 +101,10 @@ bpl-test crossmod_exception
[ bpl-test andreas_beyer ] [ bpl-test andreas_beyer ]
[ bpl-test polymorphism ] [ bpl-test polymorphism ]
[ bpl-test polymorphism2 ] [ bpl-test polymorphism2 ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr ]
[ bpl-test auto_ptr ] [ bpl-test auto_ptr ]
[ bpl-test minimal ] [ bpl-test minimal ]
[ bpl-test args ] [ bpl-test args ]
@@ -115,7 +119,7 @@ bpl-test crossmod_exception
[ bpl-test keywords : keywords.cpp keywords_test.py ] [ bpl-test keywords : keywords.cpp keywords_test.py ]
[ extension builtin_converters : test_builtin_converters.cpp <template>../build/extension ] [ extension builtin_converters : test_builtin_converters.cpp <template>../build/extension ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ] [ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters : : : -v ]
[ bpl-test test_pointer_adoption ] [ bpl-test test_pointer_adoption ]
[ bpl-test operators ] [ bpl-test operators ]
@@ -148,9 +152,12 @@ bpl-test crossmod_exception
[ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ] [ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ]
[ bpl-test stl_iterator : stl_iterator.py stl_iterator.cpp ]
[ bpl-test extract ] [ bpl-test extract ]
[ bpl-test opaque ] [ bpl-test opaque ]
[ bpl-test voidptr ]
[ bpl-test pickle1 ] [ bpl-test pickle1 ]
[ bpl-test pickle2 ] [ bpl-test pickle2 ]
@@ -164,11 +171,11 @@ bpl-test crossmod_exception
[ bpl-test vector_indexing_suite ] [ bpl-test vector_indexing_suite ]
[ bpl-test pointer_vector ] [ bpl-test pointer_vector ]
[ extension map_indexing_suite_ext [ extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp <template>../build/extension ] : map_indexing_suite.cpp int_map_indexing_suite.cpp <template>../build/extension ]
[ boost-python-runtest [ boost-python-runtest
map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext ] map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext : : : -v ]
# if $(TEST_BIENSTMAN_NON_BUGS) # if $(TEST_BIENSTMAN_NON_BUGS)
# { # {

View File

@@ -2,18 +2,6 @@
use-project /boost/python : ../build ; use-project /boost/python : ../build ;
project /boost/python/test ; project /boost/python/test ;
# A bug in the Win32 intel compilers causes compilation of one of our
# tests to take forever when debug symbols are enabled. This rule
# turns them off when added to the requirements section
#rule turn-off-intel-debug-symbols ( toolset variant : properties * )
#{
# if $(NT) && [ MATCH (.*intel.*) : $(toolset) ]
# {
# properties = [ difference $(properties) : <debug-symbols>on ] <debug-symbols>off ;
# }
# return $(properties) ;
#}
rule py-run ( sources * ) rule py-run ( sources * )
{ {
return [ run $(sources) /boost/python//boost_python ] ; return [ run $(sources) /boost/python//boost_python ] ;
@@ -40,7 +28,13 @@ rule py-compile-fail ( sources * )
test-suite python test-suite python
: :
[ run ../test/embedding.cpp ../build//boost_python /python//python ]
[
run exec.cpp ../build//boost_python
: # program args
: exec.py
: # requirements
]
[ [
bpl-test crossmod_exception bpl-test crossmod_exception
@@ -52,9 +46,15 @@ bpl-test crossmod_exception
[ bpl-test return_arg ] [ bpl-test return_arg ]
[ bpl-test staticmethod ] [ bpl-test staticmethod ]
[ bpl-test shared_ptr ] [ bpl-test shared_ptr ]
[ bpl-test andreas_beyer ]
[ bpl-test polymorphism ] [ bpl-test polymorphism ]
[ bpl-test polymorphism2 ] [ bpl-test polymorphism2 ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr ]
[ bpl-test auto_ptr ] [ bpl-test auto_ptr ]
[ bpl-test minimal ] [ bpl-test minimal ]
[ bpl-test args ] [ bpl-test args ]
[ bpl-test raw_ctor ] [ bpl-test raw_ctor ]
@@ -67,8 +67,8 @@ bpl-test crossmod_exception
[ bpl-test keywords : keywords.cpp keywords_test.py ] [ bpl-test keywords : keywords.cpp keywords_test.py ]
[ python-extension builtin_converters : test_builtin_converters.cpp /boost/python//boost_python ] [ python-extension builtin_converters.ext : test_builtin_converters.cpp /boost/python//boost_python ]
[ bpl-test builtin_converters_test : test_builtin_converters.py builtin_converters ] [ bpl-test builtin_converters : test_builtin_converters.py builtin_converters.ext ]
[ bpl-test test_pointer_adoption ] [ bpl-test test_pointer_adoption ]
[ bpl-test operators ] [ bpl-test operators ]
@@ -93,17 +93,24 @@ bpl-test crossmod_exception
[ bpl-test bienstman1 ] [ bpl-test bienstman1 ]
[ bpl-test bienstman2 ] [ bpl-test bienstman2 ]
[ bpl-test bienstman3 ] [ bpl-test bienstman3 ]
#
#[ bpl-test multi_arg_constructor [ bpl-test multi_arg_constructor
# : # files : # files
# : # requirements : # requirements
# turn-off-intel-debug-symbols ] # debug symbols slow the build down too much # A bug in the Win32 intel compilers causes compilation of one of our
# # tests to take forever when debug symbols are enabled. This rule
# turns them off when added to the requirements section
<toolset>intel-win:<debug-symbols>off
]
[ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ] [ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ]
[ bpl-test stl_iterator : stl_iterator.py stl_iterator.cpp ]
[ bpl-test extract ] [ bpl-test extract ]
[ bpl-test opaque ] [ bpl-test opaque ]
[ bpl-test voidptr ]
[ bpl-test pickle1 ] [ bpl-test pickle1 ]
[ bpl-test pickle2 ] [ bpl-test pickle2 ]
@@ -131,7 +138,7 @@ bpl-test crossmod_exception
# --- unit tests of library components --- # --- unit tests of library components ---
[ run indirect_traits_test.cpp ] [ compile indirect_traits_test.cpp ]
[ run destroy_test.cpp ] [ run destroy_test.cpp ]
[ py-run pointer_type_id_test.cpp ] [ py-run pointer_type_id_test.cpp ]
[ py-run bases.cpp ] [ py-run bases.cpp ]

View File

@@ -85,21 +85,21 @@
>>> q.f1() >>> q.f1()
(1, 4.25, 'wow') (1, 4.25, 'wow')
>>> X.f.__doc__ >>> X.f.__doc__.splitlines()[:2]
"This is X.f's docstring" ["This is X.f's docstring", 'C++ signature:']
>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5) >>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5)
>>> for f in xfuncs: >>> for f in xfuncs:
... print f(q,1).value(), ... print f(q,1).value(),
... print f(q, n = 1).value(), ... print f(q, n = 1).value(),
... print f(q, n = 0).value(), ... print f(q, n = 0).value(),
... print f.__doc__ ... print f.__doc__.splitlines()[:2]
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
1 1 0 docstring 1 1 0 ['docstring', 'C++ signature:']
>>> x = X(a1 = 44, a0 = 22) >>> x = X(a1 = 44, a0 = 22)
>>> x.inner0(0).value() >>> x.inner0(0).value()

View File

@@ -41,8 +41,8 @@ int X::counter;
struct Y : X struct Y : X
{ {
Y(PyObject* self, int x) : X(x) {}; Y(PyObject* self, int x) : X(x), self(self) {}
Y(PyObject* self, Y const& rhs) : X(rhs), self(self) {}; Y(PyObject* self, Y const& rhs) : X(rhs), self(self) {}
private: private:
Y(Y const&); Y(Y const&);
PyObject* self; PyObject* self;
@@ -50,8 +50,8 @@ struct Y : X
struct Z : X struct Z : X
{ {
Z(PyObject* self, int x) : X(x) {}; Z(PyObject* self, int x) : X(x), self(self) {}
Z(PyObject* self, Z const& rhs) : X(rhs), self(self) {}; Z(PyObject* self, Z const& rhs) : X(rhs), self(self) {}
private: private:
Z(Z const&); Z(Z const&);
PyObject* self; PyObject* self;

View File

@@ -36,20 +36,20 @@ public:
class symbol_wrapper: public symbol { class symbol_wrapper: public symbol {
public: public:
symbol_wrapper(PyObject* self): symbol() { symbol_wrapper(PyObject* /*self*/): symbol() {
name = "cltree.wrapped_symbol"; name = "cltree.wrapped_symbol";
} }
}; };
class variable_wrapper: public variable { class variable_wrapper: public variable {
public: public:
variable_wrapper(PyObject* self): variable() { variable_wrapper(PyObject* /*self*/): variable() {
name = "cltree.wrapped_variable"; name = "cltree.wrapped_variable";
} }
// This constructor is introduced only because cannot use // This constructor is introduced only because cannot use
// boost::noncopyable, see below. // boost::noncopyable, see below.
variable_wrapper(PyObject* self,variable v): variable(v) {} variable_wrapper(PyObject* /*self*/,variable v): variable(v) {}
}; };

View File

@@ -21,6 +21,7 @@ struct Y : test_class<1>
{ {
Y(int v) : test_class<1>(v) {} Y(int v) : test_class<1>(v) {}
Y& operator=(Y const& rhs) { x = rhs.x; return *this; } Y& operator=(Y const& rhs) { x = rhs.x; return *this; }
bool q;
}; };
double get_fair_value(X const& x) { return x.value(); } double get_fair_value(X const& x) { return x.value(); }
@@ -65,7 +66,7 @@ namespace
}; };
const Color3 Color3::black const Color3 Color3::black
#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) #if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
= {} = {}
#endif #endif
; ;
@@ -96,6 +97,7 @@ BOOST_PYTHON_MODULE(data_members_ext)
.def("value", &Y::value) .def("value", &Y::value)
.def("set", &Y::set) .def("set", &Y::set)
.def_readwrite("x", &Y::x) .def_readwrite("x", &Y::x)
.def_readwrite("q", &Y::q)
; ;
class_<Var>("Var", init<std::string>()) class_<Var>("Var", init<std::string>())

View File

@@ -42,6 +42,15 @@
>>> v.rw2b.x >>> v.rw2b.x
777 777
>>> Var.rw2b = Y(888) >>> Var.rw2b = Y(888)
>>> y = Y(99)
>>> y.q = True
>>> y.q
True
>>> y.q = False
>>> y.q
False
>>> Var.ro2a.x >>> Var.ro2a.x
888 888
>>> Var.ro2b.x >>> Var.ro2b.x

View File

@@ -109,17 +109,32 @@
>>> x.get_state() >>> x.get_state()
'Got exactly two arguments from constructor: string(Phoenix); bool(1); ' 'Got exactly two arguments from constructor: string(Phoenix); bool(1); '
>>> def printdoc(x): >>> def selected_doc(obj, *args):
... print x.__doc__ ... doc = obj.__doc__.splitlines()
... return "\\n".join(["|"+doc[i] for i in args])
>>> printdoc(X.__init__) >>> print selected_doc(X.__init__, 0, 2, 4, 6, 8, 9, 10, 12)
doc of init |C++ signature:
|C++ signature:
|C++ signature:
|C++ signature:
|
|doc of init
|C++ signature:
|C++ signature:
>>> printdoc(Y.__init__) >>> print selected_doc(Y.__init__, 0, 1)
doc of Y init |doc of Y init
|C++ signature:
>>> printdoc(X.bar2) >>> print selected_doc(X.bar2, 0, 2, 4, 6, 8, 9, 10)
doc of X::bar2 |C++ signature:
|C++ signature:
|C++ signature:
|C++ signature:
|
|doc of X::bar2
|C++ signature:
""" """
def run(args = None): def run(args = None):
@@ -136,48 +151,3 @@ if __name__ == '__main__':
status = run()[0] status = run()[0]
if (status == 0): print "Done." if (status == 0): print "Done."
sys.exit(status) sys.exit(status)

View File

@@ -6,6 +6,7 @@
#include <boost/python/class.hpp> #include <boost/python/class.hpp>
#include <boost/python/module.hpp> #include <boost/python/module.hpp>
#include <boost/python/def.hpp> #include <boost/python/def.hpp>
#include <boost/python/docstring_options.hpp>
#include <boost/python/scope.hpp> #include <boost/python/scope.hpp>
#include <boost/python/manage_new_object.hpp> #include <boost/python/manage_new_object.hpp>
#include "test_class.hpp" #include "test_class.hpp"
@@ -55,6 +56,42 @@ BOOST_PYTHON_MODULE(docstring_ext)
"creates a new X object"); "creates a new X object");
def("fact", fact, "compute the factorial"); def("fact", fact, "compute the factorial");
{
docstring_options doc_options;
doc_options.disable_user_defined();
def("fact_usr_off_1", fact, "usr off 1");
doc_options.enable_user_defined();
def("fact_usr_on_1", fact, "usr on 1");
doc_options.disable_user_defined();
def("fact_usr_off_2", fact, "usr off 2");
}
def("fact_usr_on_2", fact, "usr on 2");
{
docstring_options doc_options(true, false);
def("fact_sig_off_1", fact, "sig off 1");
doc_options.enable_signatures();
def("fact_sig_on_1", fact, "sig on 1");
doc_options.disable_signatures();
def("fact_sig_off_2", fact, "sig off 2");
}
def("fact_sig_on_2", fact, "sig on 2");
{
docstring_options doc_options(false);
def("fact_usr_off_sig_off_1", fact, "usr off sig off 1");
{
docstring_options nested_doc_options;
def("fact_usr_on_sig_on_1", fact, "usr on sig on 1");
nested_doc_options.disable_all();
nested_doc_options.enable_user_defined();
def("fact_usr_on_sig_off_1", fact, "usr on sig off 1");
nested_doc_options.enable_all();
def("fact_usr_on_sig_on_2", fact, "usr on sig on 2");
}
def("fact_usr_off_sig_off_2", fact, "usr off sig off 2");
}
} }
#include "module_tail.cpp" #include "module_tail.cpp"

View File

@@ -1,45 +1,103 @@
# Copyright David Abrahams 2004. Distributed under the Boost # Copyright David Abrahams & Ralf W. Grosse-Kunsteve 2004-2006.
# Software License, Version 1.0. (See accompanying # 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) # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
''' '''
>>> from docstring_ext import * >>> from docstring_ext import *
>>> def printdoc(x): >>> def selected_doc(obj, *args):
... print x.__doc__ ... doc = obj.__doc__.splitlines()
... return "\\n".join(["|"+doc[i] for i in args])
>>> printdoc(X) >>> print selected_doc(X.__init__, 0, 1, 2)
A simple class wrapper around a C++ int |this is the __init__ function
includes some error-checking |its documentation has two lines.
|C++ signature:
>>> printdoc(X.__init__) >>> print selected_doc(X.value, 0, 1, 3, 4, 5)
this is the __init__ function |gets the value of the object
its documentation has two lines. |C++ signature:
|
|also gets the value of the object
|C++ signature:
>>> printdoc(create) >>> print selected_doc(create, 0, 1)
creates a new X object |creates a new X object
|C++ signature:
>>> print selected_doc(fact, 0, 1)
|compute the factorial
|C++ signature:
>>> len(fact_usr_off_1.__doc__.splitlines())
2
>>> 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)
|usr on 1
|C++ signature:
>>> len(fact_usr_off_2.__doc__.splitlines())
2
>>> 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)
|usr on 2
|C++ signature:
>>> len(fact_sig_off_1.__doc__.splitlines())
1
>>> 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)
|sig on 1
|C++ signature:
>>> len(fact_sig_off_2.__doc__.splitlines())
1
>>> 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)
|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)
|usr on sig on 1
|C++ signature:
>>> len(fact_usr_on_sig_off_1.__doc__.splitlines())
1
>>> 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)
|usr on sig on 2
|C++ signature:
>>> print fact_usr_off_sig_off_2.__doc__
None
>>> printdoc(fact)
compute the factorial
''' '''
def check_double_string():
"""
>>> assert check_double_string() == True
"""
from docstring_ext import X
return X.value.__doc__ == "gets the value of the object\n\nalso gets the value of the object"
def run(args = None): def run(args = None):
import sys import sys
import doctest import doctest
if args is not None: if args is not None:
sys.argv = args sys.argv = args
import docstring_ext import docstring_ext
result = doctest.testmod(sys.modules.get(__name__)) result = doctest.testmod(sys.modules.get(__name__))
import pydoc import pydoc
import re import re
docmodule = lambda m: re.sub(".\10", "", pydoc.text.docmodule(m)) docmodule = lambda m: re.sub(".\10", "", pydoc.text.docmodule(m))
@@ -52,9 +110,9 @@ def run(args = None):
result = list(result) result = list(result)
result[0] += 1 result[0] += 1
return tuple(result) return tuple(result)
return result return result
if __name__ == '__main__': if __name__ == '__main__':
print "running..." print "running..."
import sys import sys

View File

@@ -1,196 +0,0 @@
// Copyright David Abrahams 2002.
// 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)
// embedded_hello -- A simple Boost.Python embedding example -- by
// Dirk Gerrits
#include <boost/python.hpp>
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <stdexcept>
#include <cassert>
namespace python = boost::python;
// An abstract base class
class Base : public boost::noncopyable
{
public:
virtual ~Base() {};
virtual std::string hello() = 0;
};
// C++ derived class
class CppDerived : public Base
{
public:
virtual ~CppDerived() {}
std::string hello()
{
return "Hello from C++!";
}
};
// Familiar Boost.Python wrapper class for Base
struct BaseWrap : public Base
{
BaseWrap(PyObject* self_)
: self(self_) {}
std::string hello() { return python::call_method<std::string>(self, "hello"); }
PyObject* self;
};
// Pack the Base class wrapper into a module
BOOST_PYTHON_MODULE(embedded_hello)
{
python::class_<Base, BaseWrap, boost::noncopyable>("Base")
;
}
void test()
{
//- INITIALIZATION -----------------------------------------------------------//
// Register the module with the interpreter
if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules");
// Retrieve the main module
python::object main_module((
python::handle<>(python::borrowed(PyImport_AddModule("__main__")))));
// Retrieve the main module's namespace
python::object main_namespace((main_module.attr("__dict__")));
// Define the derived class in Python.
// (You'll normally want to put this in a .py file.)
python::handle<> result(
PyRun_String(
"from embedded_hello import * \n"
"class PythonDerived(Base): \n"
" def hello(self): \n"
" return 'Hello from Python!' \n",
Py_file_input, main_namespace.ptr(), main_namespace.ptr())
);
// Result is not needed
result.reset();
// Extract the raw Python object representing the just defined derived class
python::handle<> class_ptr(
PyRun_String("PythonDerived\n", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr()) );
// Wrap the raw Python object in a Boost.Python object
python::object PythonDerived(class_ptr);
//- MAIN PROGRAM -------------------------------------------------------------//
// Creating and using instances of the C++ class is as easy as always.
CppDerived cpp;
std::cout << cpp.hello() << std::endl;
// But now creating and using instances of the Python class is almost
// as easy!
python::object py_base = PythonDerived();
Base& py = python::extract<Base&>(py_base)
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
()
#endif
;
std::cout << py.hello() << std::endl;
}
void
test_tutorial()
{
using namespace boost::python;
object main_module((
handle<>(borrowed(PyImport_AddModule("__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())
));
}
void
test_tutorial2()
{
using namespace boost::python;
object main_module((
handle<>(borrowed(PyImport_AddModule("__main__")))));
object main_namespace = main_module.attr("__dict__");
handle<> ignored((PyRun_String(
"result = 5 ** 2"
, Py_file_input
, main_namespace.ptr()
, main_namespace.ptr())
));
int five_squared = extract<int>(main_namespace["result"]);
assert(five_squared == 25);
object result((handle<>(
PyRun_String("5 ** 2"
, Py_eval_input
, main_namespace.ptr()
, main_namespace.ptr()))
));
int five_squared2 = extract<int>(result);
assert(five_squared2 == 25);
}
int main()
{
// Initialize the interpreter
Py_Initialize();
if (python::handle_exception(test))
{
if (PyErr_Occurred())
PyErr_Print();
return 1;
}
if (python::handle_exception(test_tutorial))
{
if (PyErr_Occurred())
PyErr_Print();
return 1;
}
if (python::handle_exception(test_tutorial2))
{
if (PyErr_Occurred())
PyErr_Print();
return 1;
}
// Boost.Python doesn't support Py_Finalize yet.
// Py_Finalize();
return 0;
}
#include "module_tail.cpp"

View File

@@ -7,7 +7,7 @@
struct error {}; struct error {};
void translate(error const& e) void translate(error const& /*e*/)
{ {
PyErr_SetString(PyExc_RuntimeError, "!!!error!!!"); PyErr_SetString(PyExc_RuntimeError, "!!!error!!!");
} }

164
test/exec.cpp Normal file
View File

@@ -0,0 +1,164 @@
// Copyright Stefan Seefeld 2005.
// 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)
#include <boost/python.hpp>
#define BOOST_ENABLE_ASSERT_HANDLER 1
#include <boost/assert.hpp>
#include <iostream>
namespace boost
{
void assertion_failed(char const * expr, char const * function,
char const * file, long line)
{
std::cerr << "assertion failed : " << expr << " in " << function
<< " at " << file << ':' << line << std::endl;
abort();
}
} // namespace boost
namespace python = boost::python;
// An abstract base class
class Base : public boost::noncopyable
{
public:
virtual ~Base() {};
virtual std::string hello() = 0;
};
// C++ derived class
class CppDerived : public Base
{
public:
virtual ~CppDerived() {}
virtual std::string hello() { return "Hello from C++!";}
};
// Familiar Boost.Python wrapper class for Base
struct BaseWrap : Base, python::wrapper<Base>
{
virtual std::string hello()
{
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// workaround for VC++ 6.x or 7.0, see
// http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
return python::call<std::string>(this->get_override("hello").ptr());
#else
return this->get_override("hello")();
#endif
}
};
// Pack the Base class wrapper into a module
BOOST_PYTHON_MODULE(embedded_hello)
{
python::class_<BaseWrap, boost::noncopyable> base("Base");
}
void exec_test()
{
// Register the module with the interpreter
if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules");
// Retrieve the main module
python::object main = python::import("__main__");
// Retrieve the main module's namespace
python::object global(main.attr("__dict__"));
// Define the derived class in Python.
python::object result = python::exec(
"from embedded_hello import * \n"
"class PythonDerived(Base): \n"
" def hello(self): \n"
" return 'Hello from Python!' \n",
global, global);
python::object PythonDerived = global["PythonDerived"];
// Creating and using instances of the C++ class is as easy as always.
CppDerived cpp;
BOOST_ASSERT(cpp.hello() == "Hello from C++!");
// But now creating and using instances of the Python class is almost
// as easy!
python::object py_base = PythonDerived();
Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
// Make sure the right 'hello' method is called.
BOOST_ASSERT(py.hello() == "Hello from Python!");
}
void exec_file_test(std::string const &script)
{
// Run a python script in an empty environment.
python::dict global;
python::object result = python::exec_file(script.c_str(), global, global);
// Extract an object the script stored in the global dictionary.
BOOST_ASSERT(python::extract<int>(global["number"]) == 42);
}
void exec_test_error()
{
// Execute a statement that raises a python exception.
python::dict global;
python::object result = python::exec("print unknown \n", global, global);
}
int main(int argc, char **argv)
{
assert(argc == 2);
std::string script = argv[1];
bool success = true;
// Initialize the interpreter
Py_Initialize();
if (python::handle_exception(exec_test) ||
python::handle_exception(boost::bind(exec_file_test, script)))
{
if (PyErr_Occurred())
{
PyErr_Print();
}
else
{
std::cerr << "A C++ exception was thrown for which "
<< "there was no exception handler registered." << std::endl;
}
success = false;
}
if (python::handle_exception(exec_test_error))
{
if (PyErr_Occurred())
{
PyErr_Print();
}
else
{
std::cerr << "A C++ exception was thrown for which "
<< "there was no exception handler registered." << std::endl;
success = false;
}
}
else
{
success = false;
}
// Boost.Python doesn't support Py_Finalize yet.
// Py_Finalize();
return success ? 0 : 1;
}
// Including this file makes sure
// that on Windows, any crashes (e.g. null pointer dereferences) invoke
// the debugger immediately, rather than being translated into structured
// exceptions that can interfere with debugging.
#include "module_tail.cpp"

2
test/exec.py Normal file
View File

@@ -0,0 +1,2 @@
print 'Hello World !'
number = 42

Some files were not shown because too many files have changed in this diff Show More