mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 18:12:43 +00:00
Compare commits
82 Commits
boost-1.33
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eceab34284 | ||
|
|
5f505d6ba8 | ||
|
|
dd30e8c45c | ||
|
|
c39836ddc8 | ||
|
|
fb35a82bf1 | ||
|
|
44c5c18f45 | ||
|
|
e0cceeb88c | ||
|
|
4a5f6f2e24 | ||
|
|
8b1748fea0 | ||
|
|
82919f0d5c | ||
|
|
1f6ded7b4e | ||
|
|
a0d2873156 | ||
|
|
0519d54229 | ||
|
|
c181874335 | ||
|
|
203a42c35f | ||
|
|
8eba0eb25b | ||
|
|
152e76220a | ||
|
|
8897cc9ce6 | ||
|
|
335cd02c2d | ||
|
|
758d92b33e | ||
|
|
28eef45d28 | ||
|
|
d8790a34d3 | ||
|
|
3b058185c6 | ||
|
|
2261e7eedc | ||
|
|
19a196493f | ||
|
|
d10b5e8d1a | ||
|
|
1cacefc226 | ||
|
|
efcd2833f1 | ||
|
|
2f9323d9e9 | ||
|
|
8b2f4b4ce0 | ||
|
|
ab046dc634 | ||
|
|
ef3f9b15f0 | ||
|
|
68463e2fd2 | ||
|
|
f75eca94e0 | ||
|
|
a23030b83e | ||
|
|
321cf2502a | ||
|
|
4996f912b4 | ||
|
|
09e24cb17d | ||
|
|
ac32d13e10 | ||
|
|
b0496d1207 | ||
|
|
a076239fc8 | ||
|
|
7cf0f9090f | ||
|
|
479f068673 | ||
|
|
9b326f15fa | ||
|
|
f094a5b9eb | ||
|
|
4367850e5d | ||
|
|
f44a4d6468 | ||
|
|
5206dd55d2 | ||
|
|
988bf849a1 | ||
|
|
6fee43fc6f | ||
|
|
6ec4387ea1 | ||
|
|
e2f59ef548 | ||
|
|
92a6fafd20 | ||
|
|
4721f5f9af | ||
|
|
3864838da2 | ||
|
|
8e77df69d5 | ||
|
|
12770b03e8 | ||
|
|
c8a692b4b4 | ||
|
|
2571ebb0c2 | ||
|
|
283dbfb593 | ||
|
|
83f227034f | ||
|
|
c5f514a4e6 | ||
|
|
9fb15f631e | ||
|
|
3d8f4c90ba | ||
|
|
5597dcb321 | ||
|
|
ab2912e3c2 | ||
|
|
b705931ff0 | ||
|
|
2974286209 | ||
|
|
1cec514b39 | ||
|
|
8ecd49cbf0 | ||
|
|
67a7669ff4 | ||
|
|
e80545a7d3 | ||
|
|
6afe0d4732 | ||
|
|
f8280b0e1a | ||
|
|
aa20ce7d2c | ||
|
|
6074a23242 | ||
|
|
9ceac3ff8f | ||
|
|
126a3efb92 | ||
|
|
9205f507b0 | ||
|
|
bff975f08c | ||
|
|
262bcee750 | ||
|
|
a3f12b18b1 |
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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: <code>c:/tools/python</code>
|
|
||||||
Unix: <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: <code>c:/Python</code><i>(10*Version)</i>, e.g. <code>c:/Python24</code>
|
||||||
|
<br>
|
||||||
|
*nix/Cygwin: <code>/usr</code></td>
|
||||||
|
|
||||||
|
<td>On *nix, this should be the <code>--prefix=</code> directory used
|
||||||
|
to configure Python when it was built and installed.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<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
|
||||||
|
|||||||
376
doc/news.html
376
doc/news.html
@@ -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<T></code> can now be used as expected with a
|
||||||
|
held type of <i>some-smart-pointer</i><code><T></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> => Python
|
<li>Support for wrapping classes with overloaded address-of
|
||||||
<code>IndexError</code> exception conversion, thanks to <a href=
|
(<code>&</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<optional<> ></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<T*></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> => 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>
|
|
||||||
>>> import test
|
>>> import test
|
||||||
>>> f(0, z = "bar")
|
>>> f(0, z = "bar")
|
||||||
>>> f(z = "bar", y = 0.0)
|
>>> 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ßauge</a> has contributed <a href=
|
Ganß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<X></code>, regardless of how it
|
to <code>shared_ptr<X></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<></code> added.</dd>
|
<dd>Full Support for <code>std::auto_ptr<></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>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002-2003.</i></p>
|
Abrahams</a> 2002-2003.</i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"> <</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">></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"><</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">></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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
<pre class="programlisting">
|
||||||
>>></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">>>></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">>>></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>
|
||||||
|
|||||||
@@ -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)
|
||||||
<library-path>$(PYTHON_LIB_PATH)
|
<library-path>$(PYTHON_LIB_PATH)
|
||||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
<find-library>$(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"><boost/python.hpp></tt><br><br>
|
#include <tt class="literal"><boost/python.hpp></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"><>(</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"><>(</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<></tt> instead of the longer, but equivalent, <tt class="literal">handle<PyObject></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<></tt>
|
||||||
|
instead of the longer, but equivalent, <tt class="literal">handle<PyObject></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"><>(</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"><>(</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"><></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"><></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"><>(</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"><>(</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"><></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"><></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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span></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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
|
||||||
|
</pre>
|
||||||
<p>
|
<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"><>(</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"><>(</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"><</span><span class="keyword">int</span><span class="special">>(</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"><</span><span class="keyword">int</span><span class="special">>(</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"><>(</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"><>(</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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span><span class="special">
|
</span> <span class="keyword">int</span> <span class="identifier">five_divided_by_zero</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||||
}</span><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"><></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"><></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">
|
||||||
|
|||||||
@@ -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">&</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">&</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"><</span><span class="identifier">
|
<span class="special">}</span>
|
||||||
PodBayDoorException</span><span class="special">>(</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"><</span>
|
||||||
|
<span class="identifier">PodBayDoorException</span><span class="special">>(</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">
|
||||||
|
|||||||
@@ -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">-></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">-></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"> <</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">></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"><</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">></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">)</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</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"> &</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">&</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"> &</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">&</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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
<pre class="programlisting">
|
||||||
>>></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">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||||
>>></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">>>></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><span class="identifier"> planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span><span class="string">
|
<span class="special">>>></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">>>></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">>>></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">>>></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">-></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">-></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_<World></tt> about the constructor we want to
|
We have to tell <tt class="literal">class_<World></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"> <</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">></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"><</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">></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</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="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</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"> &</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">&</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"> &</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">&</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<std::string>()</tt> exposes the constructor taking in a
|
</pre>
|
||||||
<tt class="literal">std::string</tt> (in Python, constructors are spelled
|
<p><tt class="literal">init<std::string>()</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<...></tt>s to
|
We can expose additional constructors by passing more <tt class="literal">init<...></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span><span class="identifier"> init</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="special">
|
</p>
|
||||||
.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</span><span class="special">>())</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"> &</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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</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"> &</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"><</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>())</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">&</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">&</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"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span><span class="identifier"> no_init</span><span class="special">)</span></tt></pre>
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
<p>
|
<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"><</span><span class="identifier">Var</span><span class="special">>(</span><span class="string">"Var"</span><span class="special">,</span><span class="identifier"> init</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="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"> &</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"> &</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"><</span><span class="identifier">Var</span><span class="special">>(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</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="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&</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">&</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">>>></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">
|
||||||
>>></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">>>></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><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">>>></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">>>></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">>>></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"> "<stdin>"</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">>>></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">"<stdin>"</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"><</span><span class="identifier">Num</span><span class="special">>(</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"> &</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"> &</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">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"><</span><span class="identifier">Num</span><span class="special">>(</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">&</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">&</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">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">>>></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">
|
||||||
>>></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">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span>
|
||||||
>>></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">>>></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">>>></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><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">>>></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"> &</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">&</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"><</span><span class="identifier">Base</span><span class="special">>(</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"><</span><span class="identifier">Base</span><span class="special">>(</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"><</span><span class="identifier">Derived</span><span class="special">,</span><span class="identifier"> bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span><span class="special"> >(</span><span class="string">"Derived"</span><span class="special">)</span><span class="comment">
|
</p>
|
||||||
/*...*/</span><span class="special">
|
<pre class="programlisting">
|
||||||
;</span></tt></pre>
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</span><span class="string">"Derived"</span><span class="special">)</span>
|
||||||
|
<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<manage_new_object></tt> to instruct Python to adopt
|
<tt class="literal">return_value_policy<manage_new_object></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"><</span><span class="identifier">manage_new_object</span><span class="special">>());</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"><</span><span class="identifier">manage_new_object</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.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"><</span><span class="identifier">Base</span><span class="special">></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">-></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"><</span><span class="identifier">Base</span><span class="special">></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">-></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"><</span><span class="identifier">Base</span><span class="special">></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"><</span><span class="identifier">Base</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
as:<br><br><tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</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"><</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><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">(&</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"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||||
<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">(&</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"><</span><span class="identifier">Base</span><span class="special">></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"><</span><span class="identifier">Base</span><span class="special">></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">-></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">-></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">-></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">-></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"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</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"><</span><span class="keyword">char</span><span class="keyword"> const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</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"><</span><span class="identifier">BaseWrap</span><span class="special">,</span><span class="identifier"> boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span><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"> &</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="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"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||||
|
<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">&</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="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">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>.
|
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
|
||||||
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">>>></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">
|
||||||
>>></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">>>></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">>>></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>
|
||||||
>>></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">>>></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">>>></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">>>></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">>>></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">>>></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">&</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="special">&</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">&</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="keyword">
|
<span class="identifier">FilePos</span><span class="special">&</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>
|
||||||
bool</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></tt></pre>
|
<span class="keyword">bool</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>
|
||||||
|
</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"><</span><span class="identifier">FilePos</span><span class="special">>(</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"><</span><span class="identifier">FilePos</span><span class="special">>(</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"><</span><span class="keyword">int</span><span class="special">>())</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"> <</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"><</span><span class="keyword">int</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="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<T>()</tt> in place of an actual
|
expression is (cheaply) default-constructible. You can use <tt class="literal">other<T>()</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">&</span><span class="keyword"> operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span><span class="identifier">
|
<span class="identifier">ostream</span><span class="special">&</span> <span class="keyword">operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span>
|
||||||
|
|
||||||
class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</span><span class="string">"Rational"</span><span class="special">)</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</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"><</span><span class="identifier">Rational</span><span class="special">>))</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"><</span><span class="identifier">Rational</span><span class="special">>))</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"><<</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"><<</span></tt> to do its work (i.e.
|
What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt> requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>
|
||||||
<tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.</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">
|
||||||
|
|||||||
@@ -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">>>> import this</tt>.</p>
|
<tt class="literal">>>> import this</tt>.
|
||||||
<pre class="programlisting"><tt class="literal">>>> import this
|
</p>
|
||||||
|
<pre class="programlisting">>>> 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">&</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">);</span></tt></pre>
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span>
|
||||||
|
</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">>>></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>
|
||||||
>>></span><span class="identifier"> del</span><span class="identifier"> y</span><span class="special">
|
<pre class="programlisting">
|
||||||
>>></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">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">y</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||||
|
</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">&</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">)</span><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">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||||
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& is tied to the lifetime
|
The problem is that the lifetime of result X& 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">>>></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">>>></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">>>></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">>>></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">-></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">-></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">>>></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>
|
||||||
>>></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">
|
||||||
>>></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">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> # <span class="identifier">Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||||
|
</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">&</span><span class="identifier"> f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span><span class="identifier"> y</span><span class="special">,</span><span class="identifier"> Z</span><span class="special">*</span><span class="identifier"> z</span><span class="special">)</span><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">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||||
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->value()</tt> is called
|
<tt class="literal">z->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"><</span><span class="number">1</span><span class="special">,</span><span class="identifier">
|
<pre class="programlisting">
|
||||||
with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span><span class="number"> 2</span><span class="special">></span><span class="special"> >());</span></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"><</span><span class="number">1</span><span class="special">,</span>
|
||||||
|
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span> <span class="special">>());</span>
|
||||||
|
</pre>
|
||||||
<p>
|
<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"><</span><span class="number">1</span></tt></pre>
|
ask?
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span>
|
||||||
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Informs Boost.Python that the first argument, in our case <tt class="literal">Y& y</tt>, is the
|
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&
|
||||||
owner of the returned reference: <tt class="literal">X&</tt>. The "<tt class="literal">1</tt>" simply specifies the
|
y</tt>, is the owner of the returned reference: <tt class="literal">X&</tt>.
|
||||||
first argument. In short: "return an internal reference <tt class="literal">X&</tt> owned by the
|
The "<tt class="literal">1</tt>" simply specifies the first argument.
|
||||||
1st argument <tt class="literal">Y& y</tt>".</p>
|
In short: "return an internal reference <tt class="literal">X&</tt> owned
|
||||||
<pre class="programlisting"><tt class="literal"><span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span><span class="number"> 2</span><span class="special">></span></tt></pre>
|
by the 1st argument <tt class="literal">Y& y</tt>".
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span>
|
||||||
|
</pre>
|
||||||
<p>
|
<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& y</tt>).</p>
|
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&
|
||||||
|
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"><</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier">
|
</p>
|
||||||
policy2</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span><span class="identifier">
|
<pre class="programlisting">
|
||||||
policy3</span><span class="special"><</span><span class="identifier">args</span><span class="special">...></span><span class="special"> ></span><span class="special"> ></span></tt></pre>
|
<span class="identifier">policy1</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span>
|
||||||
|
<span class="identifier">policy2</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span>
|
||||||
|
<span class="identifier">policy3</span><span class="special"><</span><span class="identifier">args</span><span class="special">...></span> <span class="special">></span> <span class="special">></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<T> with T one of:</b></span><br>
|
<span class="bold"><b>return_value_policy<T> 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"> &</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"> &</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"> &</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">&</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"> &</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">&</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">&</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">&</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"> &</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">&</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<...></tt>? For example,
|
arguments or a sequence of overloads. Remember <tt class="literal">init<...></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"><</span><span class="keyword">int</span><span class="special">,</span><span class="identifier"> optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span><span class="identifier"> std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span><span class="keyword"> double</span><span class="special">></span><span class="special"> >())</span></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"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></span> <span class="special">>())</span>
|
||||||
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></tt> to signify the default
|
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></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"> &</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"> &</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">&</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">&</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">
|
||||||
|
|||||||
@@ -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
|
||||||
<template>@boost/libs/python/build/extension
|
<template>@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
|
||||||
<template>@boost/libs/python/build/extension
|
<template>@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">>>></span><span class="keyword"> import</span><span class="identifier"> hello</span><span class="special">
|
<pre class="programlisting">
|
||||||
>>></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">>>></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">>>></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">
|
||||||
|
|||||||
@@ -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"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special"> >();</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"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>();</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_<>:</p>
|
Or for use in class_<>:
|
||||||
<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"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></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">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>())</span>
|
||||||
|
</pre>
|
||||||
<p><span class="bold"><b>range</b></span></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<Policies,Target>(start, finish)
|
range<Policies,Target>(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<T, Policies>()
|
iterator<T, Policies>()
|
||||||
</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 &T::begin, &T::end.</p>
|
calls <tt class="literal">range</tt> with &T::begin, &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"><</span><span class="identifier">F</span><span class="special">>(</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span><span class="special"> &</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"><</span><span class="identifier">F</span><span class="special">>(</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span><span class="special"> &</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span></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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span> <span class="special">&</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">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
|
||||||
|
</pre>
|
||||||
|
<p><span class="bold"><b>stl_input_iterator</b></span></p>
|
||||||
|
<p>
|
||||||
|
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
|
||||||
|
we wish to go the other way, though: we'd like to pass a Python sequence to
|
||||||
|
an STL algorithm or use it to initialize an STL container. We need to make
|
||||||
|
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></tt>.
|
||||||
|
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">>&</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"><</span><span class="identifier">T</span><span class="special">></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<int>
|
||||||
|
</span><span class="identifier">class_</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>(</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">&</span><span class="identifier">list_assign</span><span class="special"><</span><span class="keyword">int</span><span class="special">>)</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">
|
||||||
|
|||||||
@@ -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"> ==></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">==></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">>>></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">>>></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">>>></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">>>></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_<T> as objects</h2>
|
<a name="id455806"></a>
|
||||||
|
class_<T> as objects
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt> may
|
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></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"><</span><span class="identifier">Vec2</span><span class="special">>(</span><span class="string">"Vec2"</span><span class="special">,</span><span class="identifier"> init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span><span class="keyword"> double</span><span class="special">>())</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"> &</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"> &</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"><</span><span class="identifier">Vec2</span><span class="special">>(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>())</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">&</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">&</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<T></tt> function. Consider the following:</p>
|
object instances. This can be achieved with the <tt class="literal">extract<T></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"><</span><span class="keyword">double</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="identifier">
|
</p>
|
||||||
Vec2</span><span class="special">&</span><span class="identifier"> v</span><span class="special"> =</span><span class="identifier"> extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&>(</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"><</span><span class="keyword">double</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="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&>(</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"><</span><span class="identifier">Vec2</span><span class="special">&></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">&</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<T></tt>
|
<span class="identifier">extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&></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"><</span><span class="identifier">dict</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="identifier">
|
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
|
||||||
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<T></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"><</span><span class="identifier">dict</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="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"><</span><span class="identifier">choice</span><span class="special">>(</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"><</span><span class="identifier">choice</span><span class="special">>(</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">>>></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">>>></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"><</span><span class="identifier">X</span><span class="special">>(</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"><</span><span class="identifier">X</span><span class="special">>(</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"><</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">>(</span><span class="string">"nested"</span><span class="special">)</span><span class="special">
|
</span><span class="identifier">enum_</span><span class="special"><</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">>(</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">
|
||||||
|
|||||||
@@ -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">>>></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">
|
||||||
>>></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">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span>
|
||||||
>>></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">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||||
>>></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">>>></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> <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">>>></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">
|
||||||
>>></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">>>></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">>>></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">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
</p>
|
||||||
>>></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">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</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>
|
||||||
|
</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">>>></span><span class="keyword"> import</span><span class="identifier"> sounds</span><span class="special">.</span><span class="identifier">filters</span><span class="special">
|
</p>
|
||||||
>>></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">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</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_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">>>></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>
|
||||||
>>></span><span class="special">
|
<pre class="programlisting">
|
||||||
>>></span><span class="comment"> # a regular function
|
<span class="special">>>></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">>>></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">>>></span>
|
||||||
>>></span><span class="special">
|
<span class="special">>>></span> <span class="comment"># a regular function
|
||||||
>>></span><span class="comment"> # now we turn it in a member function
|
</span><span class="special">>>></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">>>></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">>>></span>
|
||||||
>>></span><span class="special">
|
<span class="special">>>></span> <span class="comment"># now we turn it in a member function
|
||||||
>>></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">>>></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><span class="keyword"> print</span><span class="identifier"> c</span><span class="identifier">
|
<span class="special">>>></span>
|
||||||
A</span><span class="identifier"> C</span><span class="identifier"> instance</span><span class="special">!</span><span class="special">
|
<span class="special">>>></span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C</span><span class="special">()</span>
|
||||||
>>></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">>>></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">>>></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"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">point</span><span class="special">>(</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">>>></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">
|
||||||
>>></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">>>></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">>>></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"> <</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
<span class="comment">/* file point.cpp */</span>
|
||||||
#include</span><span class="special"> <</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">></span><span class="keyword">
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span>
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</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">></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"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">point</span><span class="special">>(</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"> <</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span>
|
||||||
#include</span><span class="special"> <</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">></span><span class="keyword">
|
<span class="preprocessor">#include</span> <span class="special"><</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">></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"><</span><span class="identifier">triangle</span><span class="special">>(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">triangle</span><span class="special">>(</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"> <</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">></span><span class="preprocessor">
|
</p>
|
||||||
#include</span><span class="special"> <</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="preprocessor">
|
<pre class="programlisting">
|
||||||
#include</span><span class="special"> <</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span><span class="identifier">
|
<span class="preprocessor">#include</span> <span class="special"><</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">></span>
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">point</span><span class="special">.</span><span class="identifier">h</span><span class="special">></span>
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">triangle</span><span class="special">.</span><span class="identifier">h</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"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span><span class="identifier">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">point</span><span class="special">>(</span><span class="string">"point"</span><span class="special">)...;</span>
|
||||||
class_</span><span class="special"><</span><span class="identifier">triangle</span><span class="special">>(</span><span class="string">"triangle"</span><span class="special">)...;</span><span class="special">
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">triangle</span><span class="special">>(</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">
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ call_method<ResultType>(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& x)
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code><a href=
|
<td><code><a href=
|
||||||
"../../../bind/ref.html#reference_wrapper">boost::reference_wrapper</a><T></code></td>
|
"../../../bind/ref.html">boost::reference_wrapper</a><T></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
336
doc/v2/docstring_options.html
Normal file
336
doc/v2/docstring_options.html
Normal 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 -
|
||||||
|
<boost/python/docstring_options.hpp></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
|
||||||
|
<boost/python/docstring_options.hpp></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 <boost/python/module.hpp>
|
||||||
|
#include <boost/python/def.hpp>
|
||||||
|
#include <boost/python/docstring_options.hpp>
|
||||||
|
|
||||||
|
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>
|
||||||
|
>>> import demo
|
||||||
|
>>> print demo.foo.__doc__
|
||||||
|
foo doc
|
||||||
|
C++ signature:
|
||||||
|
foo(void) -> void
|
||||||
|
</pre>If compiled with
|
||||||
|
<code>-DDEMO_DOCSTRING_SHOW_ALL=false</code>:
|
||||||
|
<pre>
|
||||||
|
>>> import demo
|
||||||
|
>>> print demo.foo.__doc__
|
||||||
|
None
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4>Selective suppressions</h4>
|
||||||
|
<pre>
|
||||||
|
#include <boost/python/module.hpp>
|
||||||
|
#include <boost/python/def.hpp>
|
||||||
|
#include <boost/python/args.hpp>
|
||||||
|
#include <boost/python/docstring_options.hpp>
|
||||||
|
|
||||||
|
int foo1(int i) { return i; }
|
||||||
|
int foo2(long l) { return static_cast<int>(l); }
|
||||||
|
int foo3(float f) { return static_cast<int>(f); }
|
||||||
|
int foo4(double d) { return static_cast<int>(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>
|
||||||
|
>>> import demo
|
||||||
|
>>> print demo.foo1.__doc__
|
||||||
|
foo1 doc
|
||||||
|
C++ signature:
|
||||||
|
foo1(int i) -> int
|
||||||
|
>>> print demo.foo2.__doc__
|
||||||
|
C++ signature:
|
||||||
|
foo2(long l) -> int
|
||||||
|
>>> print demo.foo3.__doc__
|
||||||
|
None
|
||||||
|
>>> print demo.foo4.__doc__
|
||||||
|
foo4 doc
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4>Wrapping from multiple C++ scopes</h4>
|
||||||
|
<pre>
|
||||||
|
#include <boost/python/module.hpp>
|
||||||
|
#include <boost/python/def.hpp>
|
||||||
|
#include <boost/python/args.hpp>
|
||||||
|
#include <boost/python/docstring_options.hpp>
|
||||||
|
|
||||||
|
int foo1(int i) { return i; }
|
||||||
|
int foo2(long l) { return static_cast<int>(l); }
|
||||||
|
|
||||||
|
int bar1(int i) { return i; }
|
||||||
|
int bar2(long l) { return static_cast<int>(l); }
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void wrap_foos()
|
||||||
|
{
|
||||||
|
using namespace boost::python;
|
||||||
|
// no docstring_options here
|
||||||
|
// -> 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>
|
||||||
|
>>> import demo
|
||||||
|
>>> print demo.foo1.__doc__
|
||||||
|
None
|
||||||
|
>>> print demo.foo2.__doc__
|
||||||
|
None
|
||||||
|
>>> print demo.bar1.__doc__
|
||||||
|
bar1 doc
|
||||||
|
>>> 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>© Copyright <a href=
|
||||||
|
"../../../../people/ralf_w_grosse_kunstleve.htm">Ralf W.
|
||||||
|
Grosse-Kunstleve</a> 2006.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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
142
doc/v2/exec.html
Normal 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 - <boost/python/exec.hpp></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 <boost/python/exec.hpp></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 <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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<std::string>(greet());
|
||||||
|
std::cout << message << 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>© Copyright Stefan Seefeld 2005.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -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)) &FXThread::setAutoDelete)</pre>
|
.def("setAutoDelete", (bool (FXThread::*)(bool)) &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", &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>
|
||||||
|
|||||||
@@ -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
87
doc/v2/import.html
Normal 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 - <boost/python/import.hpp></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 <boost/python/import.hpp></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 <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
|
||||||
|
void print_python_version()
|
||||||
|
{
|
||||||
|
// Load the sys module.
|
||||||
|
object sys = import("sys");
|
||||||
|
|
||||||
|
// Extract the python version.
|
||||||
|
std::string version = extract<std::string>(sys.attr("version"));
|
||||||
|
std::cout << version << std::endl;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Revised 01 November, 2005</p>
|
||||||
|
|
||||||
|
<p><i>© Copyright Stefan Seefeld 2005.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -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 <boost/python/indexing/indexing_suite.hpp>
|
<h3> <a name="indexing_suite"></a>indexing_suite [ Header <boost/python/indexing/indexing_suite.hpp>
|
||||||
]</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 <boost/python/indexing/map_indexing_suite.hpp> ] </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_<std::map<X> >("XMap")
|
||||||
|
.def(map_indexing_suite<std::map<X> >())
|
||||||
|
;
|
||||||
|
</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<<br>
|
||||||
<h3>
|
</tt><tt>class Container<br>
|
||||||
<br>
|
|
||||||
<tt>indexing_suite<<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>
|
<td>
|
||||||
|
|
||||||
</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> </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>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
The container's index type.
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<tt>Container::size_type</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<pre>
|
<pre>
|
||||||
template <<br> class Container
|
template <<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
|
||||||
><br> class indexing_suite
|
><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&
|
||||||
static element_type&
|
|
||||||
get_item(Container& container, index_type i);
|
get_item(Container& container, index_type i);
|
||||||
|
|
||||||
static object
|
static object
|
||||||
get_slice(Container& container, index_type from, index_type to);
|
get_slice(Container& container, index_type from, index_type to);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_item(Container& container, index_type i, element_type const& v);
|
set_item(Container& container, index_type i, data_type const& v);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_slice(
|
set_slice(
|
||||||
Container& container, index_type from,
|
Container& container, index_type from,
|
||||||
index_type to, element_type const& v
|
index_type to, data_type const& v
|
||||||
);
|
);
|
||||||
|
|
||||||
template <class Iter>
|
template <class Iter>
|
||||||
@@ -593,16 +596,16 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<pre>
|
<pre>
|
||||||
template <<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class vector_indexing_suite<br> : public indexing_suite<Container, DerivedPolicies, NoProxy><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&<br> get_item(Container& container, index_type i);
|
template <<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&<br> get_item(Container& container, index_type i);
|
||||||
|
|
||||||
static object
|
static object
|
||||||
get_slice(Container& container, index_type from, index_type to);
|
get_slice(Container& container, index_type from, index_type to);
|
||||||
|
|
||||||
static void<br> set_item(Container& container, index_type i, element_type const& v);
|
static void<br> set_item(Container& container, index_type i, data_type const& v);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_slice(Container& container, index_type from,
|
set_slice(Container& container, index_type from,
|
||||||
index_type to, element_type const& v);
|
index_type to, data_type const& v);
|
||||||
|
|
||||||
template <class Iter><br> static void<br> set_slice(Container& container, index_type from,<br> index_type to, Iter first, Iter last);
|
template <class Iter><br> static void<br> set_slice(Container& 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<<br>
|
||||||
|
class <font color="#007F00">Container</font><br>
|
||||||
|
, bool <font color="#007F00">NoProxy</font><br>
|
||||||
|
, class <font color="#007F00">DerivedPolicies</font>></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> </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> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<pre>
|
||||||
|
template <<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&<br> get_item(Container& container, index_type i);
|
||||||
|
|
||||||
|
static void<br> set_item(Container& container, index_type i, data_type const& v);
|
||||||
|
|
||||||
|
static void
|
||||||
|
delete_item(Container& container, index_type i);<br>
|
||||||
|
static size_t
|
||||||
|
size(Container& container);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
contains(Container& container, key_type const& key);
|
||||||
|
|
||||||
|
static bool<br> compare_index(Container& container, index_type a, index_type b);
|
||||||
|
<br> static index_type
|
||||||
|
convert_index(Container& container, PyObject* i);
|
||||||
|
};
|
||||||
|
|
||||||
|
</pre>
|
||||||
<hr>
|
<hr>
|
||||||
© Copyright Joel de Guzman 2003. Permission to copy, use, modify,
|
© 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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ This macro generates two functions in the scope where it is used:
|
|||||||
and <code>void init_module_<i>name</i>()</code>, whose body must
|
and <code>void 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
|
||||||
|
|||||||
@@ -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 object</code>.</p>
|
access to a <code>const 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<class R> object& operator|=(object&l,R const&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& 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 < seq.attr("__len__")(); ++i)
|
for (int i = 0; i < 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>© Copyright <a href=
|
<p><i>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
|
|
||||||
<p><code><boost/python/pointee.hpp></code> introduces a
|
<p><code><boost/python/pointee.hpp></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<T></code> which can be used to extract the "pointed-to" type from the type of a pointer or smart pointer.
|
template <code>pointee<T></code> that can be used to extract the "pointed-to" type from the type of a pointer or smart pointer.
|
||||||
|
|
||||||
<h2><a name="classes"></a>Classes</h2>
|
<h2><a name="classes"></a>Classes</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -102,9 +102,9 @@ template <class T> 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><T,V>
|
"to_python_indirect.html#to_python_indirect-spec">to_python_indirect</a><T,V>
|
||||||
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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -121,13 +121,14 @@ scope();
|
|||||||
|
|
||||||
<p>C++ Module definition:</p>
|
<p>C++ Module definition:</p>
|
||||||
<pre>
|
<pre>
|
||||||
|
#include <boost/python/module.hpp>
|
||||||
#include <boost/python/class.hpp>
|
#include <boost/python/class.hpp>
|
||||||
#include <boost/python/scope.hpp>
|
#include <boost/python/scope.hpp>
|
||||||
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_<Y>("Y")
|
class_<X::Y>("Y")
|
||||||
.def("g", &Y::g)
|
.def("g", &X::Y::g)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|||||||
@@ -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. Equivalent to the slice object created
|
values. 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
270
doc/v2/stl_iterator.html
Executable file
@@ -0,0 +1,270 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<title>Boost.Python - <boost/python/stl_iterator.hpp></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 <boost/python/stl_iterator.hpp></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><boost/python/stl_iterator.hpp></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<T></code> hold a Python
|
||||||
|
iterator and adapt it for use with STL algorithms.
|
||||||
|
<code>stl_input_iterator<T></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<ValueType></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 <class ValueType>
|
||||||
|
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& ob);
|
||||||
|
|
||||||
|
stl_input_iterator& operator++();
|
||||||
|
stl_input_iterator operator++(int);
|
||||||
|
|
||||||
|
ValueType operator*() const;
|
||||||
|
|
||||||
|
friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
|
||||||
|
friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& 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& 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->it</code>. Then, calls <code>this->it.attr("next")()</code> and
|
||||||
|
stores the result in <code>this->ob</code>. If the sequence is exhausted, sets
|
||||||
|
<code>this->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& operator++()
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<dl class="function-semantics">
|
||||||
|
<dt><b>Effects:</b>
|
||||||
|
Calls <code>this->it.attr("next")()</code> and stores the result in
|
||||||
|
<code>this->ob</code>. If the sequence is exhausted, sets <code>this->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<ValueType>(this->ob);</code>
|
||||||
|
</dt>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& 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& lhs, stl_input_iterator const& 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 <boost/python/object.hpp>
|
||||||
|
#include <boost/python/stl_iterator.hpp>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
std::list<int> sequence_to_int_list(object const& ob)
|
||||||
|
{
|
||||||
|
stl_input_iterator<int> begin(ob), end;
|
||||||
|
return std::list<int>(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>
|
||||||
@@ -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
|
|
||||||
@@ -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))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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&) {}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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*/, ...) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
76
include/boost/python/docstring_options.hpp
Executable file
76
include/boost/python/docstring_options.hpp
Executable 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
|
||||||
31
include/boost/python/exec.hpp
Normal file
31
include/boost/python/exec.hpp
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
22
include/boost/python/import.hpp
Normal file
22
include/boost/python/import.hpp
Normal 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
|
||||||
@@ -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(); \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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&);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
27
include/boost/python/object/stl_iterator_core.hpp
Executable file
27
include/boost/python/object/stl_iterator_core.hpp
Executable 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 ¤t() const;
|
||||||
|
private:
|
||||||
|
boost::python::object it_;
|
||||||
|
boost::python::handle<> ob_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}} // namespace boost::python::object
|
||||||
|
|
||||||
|
#endif // STL_ITERATOR_CORE_EAN20051028_HPP
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
61
include/boost/python/stl_iterator.hpp
Executable file
61
include/boost/python/stl_iterator.hpp
Executable 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
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|||||||
@@ -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
45
src/exec.cpp
Normal 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
25
src/import.cpp
Normal 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
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
42
src/object/stl_iterator.cpp
Executable 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
|
||||||
19
test/Jamfile
19
test/Jamfile
@@ -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)
|
||||||
# {
|
# {
|
||||||
|
|||||||
@@ -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 ]
|
||||||
|
|||||||
18
test/args.py
18
test/args.py
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
|
||||||
@@ -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
164
test/exec.cpp
Normal 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
2
test/exec.py
Normal 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
Reference in New Issue
Block a user