2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 16:52:15 +00:00

Compare commits

...

73 Commits

Author SHA1 Message Date
nobody
b2e04cd704 This commit was manufactured by cvs2svn to create tag 'minmax'.
[SVN r22393]
2004-02-26 10:35:28 +00:00
Daniel Wallin
a9c2a95366 boost logo css class
[SVN r22352]
2004-02-21 18:42:52 +00:00
Bruno da Silva de Oliveira
29f3891a68 - Generates the unique number for UniqueInt using the hash of the filename
[SVN r22329]
2004-02-19 22:26:54 +00:00
Bruno da Silva de Oliveira
7b602ef607 - now warns that AllFromHeader is not working in all cases
[SVN r22316]
2004-02-18 22:32:58 +00:00
Bruno da Silva de Oliveira
15e555c7f1 - Fixed UniqueInt bug across different compilation units.
[SVN r22315]
2004-02-18 22:28:28 +00:00
Bruno da Silva de Oliveira
f4fb49d32f - reverted previous commit
[SVN r22313]
2004-02-18 15:33:34 +00:00
Bruno da Silva de Oliveira
89be2fb736 - no_init is now generated for abstract classes
[SVN r22312]
2004-02-18 15:27:59 +00:00
Ralf W. Grosse-Kunstleve
62f0885852 Requires: n/a removed
[SVN r22257]
2004-02-13 18:20:43 +00:00
Ralf W. Grosse-Kunstleve
355e155e69 gcc 3.4 from gcc.gnu.org still suffers from the old static initialization bug under Mac OS 10: workaround adjusted accordingly
[SVN r22255]
2004-02-13 07:10:59 +00:00
Ralf W. Grosse-Kunstleve
ae1584ff3c class_::enable_pickling() in publicized interface; tested with everything incl. VC6 and 7.0
[SVN r22254]
2004-02-13 05:32:38 +00:00
Jonathan Brandmeyer
4a7686cd33 Check rich slicing of Numeric arrays only if Numeric or numarray is
installed.


[SVN r22252]
2004-02-13 02:07:21 +00:00
Jonathan Brandmeyer
799eeb0cb8 Fix a build error on Tru64. Thanks to Ralf W. Grosse-Kunstleve for this
fix.


[SVN r22250]
2004-02-12 23:09:10 +00:00
Jonathan Brandmeyer
8452e275d0 New implementation, tests, and documentation for a PySliceObject
objectmanager.


[SVN r22192]
2004-02-07 21:38:24 +00:00
Joel de Guzman
53268000e7 small typo
[SVN r22067]
2004-01-30 06:15:32 +00:00
Dave Abrahams
52febfe3fc Improved and alphabetized news format, added Python news, updated
iterator news.

Corrections in the Python documentation


[SVN r22039]
2004-01-29 03:34:23 +00:00
Dave Abrahams
8fcfed495a Fixes for intel-linux
added <default> feature handling for specifying build defaults in requirement sets.


[SVN r22027]
2004-01-28 22:50:18 +00:00
Joel de Guzman
2dfe76b082 small typo
[SVN r22026]
2004-01-28 22:45:35 +00:00
Ralf W. Grosse-Kunstleve
11d8751d29 workaround for gcc 3.4 bug when using precompiled header support
[SVN r21715]
2004-01-14 01:37:54 +00:00
Ralf W. Grosse-Kunstleve
b03c3a29e0 previous revision (1.10) of this file restored because http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13530 is fixed
[SVN r21633]
2004-01-12 18:02:28 +00:00
Joel de Guzman
53e8982e05 fix typo
[SVN r21571]
2004-01-10 02:53:06 +00:00
Ralf W. Grosse-Kunstleve
4a30841ad8 fix for Tru64 cxx problems incl. workaround for gcc 2.96 problems; patch by David Abrahams; thanks Dave!
[SVN r21558]
2004-01-09 07:25:17 +00:00
Dave Abrahams
234ebadb8d pro9 workarounds; some ADL protection for is_xxx
[SVN r21529]
2004-01-07 14:07:21 +00:00
Dave Abrahams
11ee20fa36 Test full slicing.
[SVN r21497]
2004-01-05 12:34:25 +00:00
Dave Abrahams
440599545f Workaround for gcc-3.4 quirks
[SVN r21493]
2004-01-05 11:46:30 +00:00
Dave Abrahams
44ba088cb4 Fix problem with [:] slices on python::objects
[SVN r21472]
2004-01-04 13:41:00 +00:00
Dave Abrahams
08d3798722 .
[SVN r21449]
2004-01-02 18:34:17 +00:00
Ralf W. Grosse-Kunstleve
56ff8e438e fix use of incomplete type (Tru64 cxx diagnostic)
[SVN r21444]
2004-01-02 08:31:21 +00:00
Dave Abrahams
3590a3589d Fix 2-phase lookup bug
[SVN r21442]
2004-01-01 12:46:04 +00:00
Dave Abrahams
7674c82e1f Fix bug with (arg("x"), "y") construct.
[SVN r21437]
2003-12-31 19:20:31 +00:00
Ralf W. Grosse-Kunstleve
b93b21a7f2 work around Visual C++ 6 internal compiler errors
[SVN r21435]
2003-12-31 17:18:03 +00:00
Ralf W. Grosse-Kunstleve
f53925848c work around g++ (GCC) 3.4.0 20031230 (experimental) internal compiler error
[SVN r21432]
2003-12-31 09:37:31 +00:00
Dave Abrahams
eedc88b56a Bug fixes in property handling
[SVN r21429]
2003-12-31 00:23:52 +00:00
Ralf W. Grosse-Kunstleve
1102fec2a0 links to pickle and indexing suites
[SVN r21423]
2003-12-30 03:54:21 +00:00
Ralf W. Grosse-Kunstleve
589fefe4b9 tabs -> spaces
[SVN r21405]
2003-12-27 06:22:29 +00:00
Rene Rivera
cfc867bd18 Fix broken links.
[SVN r21404]
2003-12-27 02:37:02 +00:00
Rene Rivera
5bc28e3016 Fix broken links.
[SVN r21403]
2003-12-27 01:46:04 +00:00
Rene Rivera
23b7ccca7f Fix broken links. And some minor consistency changes.
[SVN r21402]
2003-12-27 01:31:00 +00:00
Dave Abrahams
e9d6286a1d Fix Dereferenceable concept to require pointee, and
register_ptr_to_python to require Dereferenceable.


[SVN r21327]
2003-12-18 19:25:14 +00:00
Dave Abrahams
48321857e4 consistent use of get_pointer
[SVN r21326]
2003-12-18 19:23:38 +00:00
Ralf W. Grosse-Kunstleve
156da15715 unused member function removed (to avoid Linux Intel C++ 8.0 warning)
[SVN r21278]
2003-12-16 04:14:28 +00:00
Ralf W. Grosse-Kunstleve
4a0d7965cb consolidation of workarounds for missing "not" keyword
[SVN r21276]
2003-12-15 17:55:38 +00:00
Dave Abrahams
1f522823ff gcc2 workaround
[SVN r21274]
2003-12-15 14:45:07 +00:00
Beman Dawes
6795a280fd tabs to spaces
[SVN r21080]
2003-12-02 13:32:47 +00:00
Dave Abrahams
f369e22638 Cleaner code using object instead of handle
[SVN r21018]
2003-11-30 21:12:30 +00:00
Dave Abrahams
a278da2eba correct get_pointer usage
[SVN r21017]
2003-11-30 21:10:15 +00:00
Dave Abrahams
37b2bdba79 Workaround gcc-2.x ICE
[SVN r21016]
2003-11-30 21:08:19 +00:00
Dave Abrahams
e9519db974 Make Dereferenceable use get_pointer
Re-enable map_indexing_suite iteration for vc6.


[SVN r21008]
2003-11-29 22:12:18 +00:00
Ralf W. Grosse-Kunstleve
dd7a24ebce links to newly generated tutorial sections
[SVN r20934]
2003-11-24 05:53:13 +00:00
Bruno da Silva de Oliveira
bc92a7d155 - added new "General Techniques" section
[SVN r20927]
2003-11-23 21:24:54 +00:00
Dave Abrahams
a68db84df6 * Fixed Boost.Thread jamfile to add the missing #include paths
* Modified Python testing code to use the facilities of testing.jam,
  so that it can be processed with process_jam_log

* Updated Python library tests to use a test suite

* Added Python test suite to status/Jamfile

* Added --run-all-tests option to force tests to run even when up-to-date.


Also,
boost-base.jam:

    Added some missing rule signatures

    RUN_LD_LIBRARY_PATH became LINK_LIBPATH because it was only really
    used during linking.

    Reformed the movement of path variables up the dependency graph

    Removed the defunct Run rule

    Set up generalized constants for path manipulation

darwin-tools.jam, gcc-tools.jam:

   use LINK_LIBPATH

python.jam:

   Reformed the choice of Python executable

testing.jam:

   Refactored testing code so it could be used for Python

   Now building all environment variable setup code ahead of time

   RUN_TEST became TEST_EXE


[SVN r20815]
2003-11-15 15:41:41 +00:00
Dave Abrahams
7b9bba3190 vc6 workaround
[SVN r20814]
2003-11-15 15:16:27 +00:00
Ralf W. Grosse-Kunstleve
bcec0af232 minor fix for otherwise confusing debug output
[SVN r20796]
2003-11-12 19:55:22 +00:00
Ralf W. Grosse-Kunstleve
0d437c4102 MIPSpro 7.41 workaround
[SVN r20795]
2003-11-12 19:49:18 +00:00
Raoul Gough
feff7bccd3 Fix MSVC6 duplicate comdat (LNK1179) with multiple python::range instances
[SVN r20794]
2003-11-12 16:50:17 +00:00
Ralf W. Grosse-Kunstleve
b12de3f01b additions by Niall Douglas with heavy edits by Ralf
[SVN r20780]
2003-11-10 20:39:13 +00:00
Dave Abrahams
0d108f12e4 Better error reporting for overload resolution failures, ideas thanks
to Nikolay Mladenov.


[SVN r20770]
2003-11-10 01:02:45 +00:00
Dave Abrahams
4aca2ca33b change to binary
[SVN r20689]
2003-11-06 01:14:50 +00:00
Dave Abrahams
9a967ae514 change to binary
[SVN r20688]
2003-11-06 01:13:26 +00:00
Ralf W. Grosse-Kunstleve
9481c39874 explain workaround for a bug in Apple's compiler
[SVN r20684]
2003-11-05 19:19:50 +00:00
Dave Abrahams
1e02065982 Fix Mike Rovner's warning suppression.
[SVN r20673]
2003-11-05 00:43:13 +00:00
Ralf W. Grosse-Kunstleve
1fee0da689 patch by Mike Rovner: work around gcc 3.3.1 bug (http://gcc.gnu.org/PR12163)
[SVN r20672]
2003-11-05 00:30:46 +00:00
Ralf W. Grosse-Kunstleve
c760cf8418 workaround for MIPSpro 7.3.1; old workaround for VC7.1 visible only to that particular compiler
[SVN r20668]
2003-11-04 20:20:07 +00:00
Ralf W. Grosse-Kunstleve
cdee5997af obsolete MIPSpro workaround removed
[SVN r20667]
2003-11-04 20:17:48 +00:00
Ralf W. Grosse-Kunstleve
4289280cdc Mac OS 10 answer updated
[SVN r20666]
2003-11-04 20:05:09 +00:00
Rene Rivera
962dfa17c5 Add -bind_at_load option for MacOSX Darwin build, this prevents semaphore_wait_trap erros when loaded by extensions.
[SVN r20665]
2003-11-04 18:30:37 +00:00
Ralf W. Grosse-Kunstleve
0a21aef601 fix expected output; tested with Python 2.2.1 (Redhat8) and Python 2.3 (Mac OS 10.2.8)
[SVN r20658]
2003-11-04 17:38:13 +00:00
Rene Rivera
8cbbd504cf Point to the new location for Boost.Build v1; tools/build/v1.
[SVN r20654]
2003-11-04 17:07:15 +00:00
Dave Abrahams
91b23c8367 Warning suppression thanks to Mike Rovner <mike-at-bindkey.com>
[SVN r20617]
2003-11-03 20:45:21 +00:00
Dave Abrahams
3729be263f Bug fix
[SVN r20566]
2003-10-30 18:40:37 +00:00
Dave Abrahams
ea91f4217a suppress a warning
[SVN r20555]
2003-10-29 23:16:36 +00:00
Raoul Gough
7fab3ce0b1 Add info on using gdb under Windows
[SVN r20554]
2003-10-29 21:38:06 +00:00
Dave Abrahams
ef7d675d67 bug fix for a single use of arg with no comma operator
[SVN r20533]
2003-10-29 00:46:08 +00:00
Rene Rivera
2b9d29a0fc Improve unused variable warning supperssion with multi-compiler friendly code.
[SVN r20466]
2003-10-24 01:19:16 +00:00
104 changed files with 2582 additions and 697 deletions

View File

@@ -34,6 +34,7 @@ if [ check-python-config ]
dict.cpp
tuple.cpp
str.cpp
slice.cpp
aix_init_module.cpp
converter/from_python.cpp
@@ -60,6 +61,7 @@ if [ check-python-config ]
<define>BOOST_PYTHON_SOURCE
$(bpl-linkflags)
<msvc-stlport><release>$(msvc-stlport-workarounds)
<darwin><*><linkflags>-bind_at_load
;
template extension

Binary file not shown.

View File

@@ -77,7 +77,7 @@
library, but if multiple Boost.Python extension modules are used
together, it will prevent sharing of types across extension modules, and
consume extra code space. To build <code>boost_python</code>, use <a
href="../../../tools/build/index.html">Boost.Build</a> in the usual way
href="../../../tools/build/v1/build_system.htm">Boost.Build</a> in the usual way
from the <code>libs/python/build</code> subdirectory of your boost
installation (if you have already built boost from the top level this may
have no effect, since the work is already done).</p>
@@ -249,7 +249,7 @@
<blockquote>
<pre>
bjam -sTOOLS=<i><a href=
"../../../tools/build/index.html#Tools">toolset</a></i> test
"../../../more/getting_started.html#Tools">toolset</a></i> test
</pre>
</blockquote>
This will update all of the Boost.Python v1 test and example targets. The
@@ -259,7 +259,7 @@ bjam -sTOOLS=<i><a href=
<blockquote>
<pre>
bjam -sTOOLS=<i><a href=
"../../../tools/build/index.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS=-v test
"../../../more/getting_started.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS=-v test
</pre>
</blockquote>
which will print each test's Python code with the expected output as it
@@ -286,11 +286,11 @@ edit the line which reads
<blockquote>
<pre>
boost-build ../../../tools/build ;
boost-build ../../../tools/build/v1 ;
</pre>
</blockquote>
so that the path refers to the <code>tools/build</code> subdirectory
so that the path refers to the <code>tools/build/v1</code> subdirectory
of your Boost installation.
@@ -311,10 +311,10 @@ so that the path refers to the root directory of your Boost installation.
<h2><a name="variants">Build Variants</a></h2>
Three <a href=
"../../../tools/build/build_system.htm#variants">variant</a>
"../../../tools/build/v1/build_system.htm#variants">variant</a>
configurations of all python-related targets are supported, and can be
selected by setting the <code><a href=
"../../../tools/build/build_system.htm#user_globals">BUILD</a></code>
"../../../tools/build/v1/build_system.htm#user_globals">BUILD</a></code>
variable:
<ul>

View File

@@ -73,6 +73,14 @@
<dt><a href="v2/reference.html">Reference Manual</a></dt>
<dt>Suites:</dt>
<dd>
<ul>
<li><a href="v2/pickle.html">Pickle</a></li>
<li><a href="v2/indexing.html">Indexing</a></li>
</ul>
</dd>
<dt><a href="v2/configuration.html">Configuration Information</a></dt>
<dt><a href="v2/platforms.html">Known Working Platforms and
@@ -114,7 +122,7 @@
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../people/dave_abrahams.htm">Dave
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
</body>
</html>

View File

@@ -17,7 +17,7 @@
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams and Brett Calcott 2003. See
accompanying <a class="reference" href="../../../LICENSE">license</a> for terms of use.</td>
accompanying <a class="reference" href="../../../LICENSE_1_0.txt">license</a> for terms of use.</td>
</tr>
</tbody>
</table>

View File

@@ -4,12 +4,13 @@
.. |(logo)| image:: ../../../c++boost.gif
:alt: Boost
:class: boost-logo
__ ../../../index.htm
.. _`Boost.Python`: index.html
.. _license: ../../../LICENSE
.. _license: ../../../LICENSE_1_0.txt
-------------------------------------------------------

View File

@@ -108,7 +108,7 @@ BOOST_PYTHON_MODULE(test)
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
Gan&szlig;auge</a> has contributed <a href=
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
<a href="nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a>
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a>
has contributed the exciting <a href="../pyste/index.html">Pyste</a>
("Pie-steh") package.</dd>

View File

@@ -26,7 +26,7 @@
</table>
<p>
It was mentioned in passing in the previous section that
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
can also be used for overloaded functions and member functions with a
common sequence of initial arguments. Here is an example:</p>
<code><pre>

View File

@@ -32,15 +32,17 @@ with every boost distribution: <b>bjam</b>.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<p><img src="theme/lens.gif"></img> <b>Building without bjam</b><br>
<br>
Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as &quot;the one and only way&quot;.
There are of course other build tools apart from <tt>bjam</tt>. </p>
<p>Take note however that the preferred build tool for Boost.Python is <tt>bjam</tt>.
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the &quot;I can't build Boost.Python&quot; problems come from
people who had to use a different tool<tt></tt>.</p></td>
<img src="theme/lens.gif"></img> <b>Building without bjam</b><br><br>
Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as &quot;the one and only way&quot;.
There are of course other build tools apart from <tt>bjam</tt>.
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the &quot;I can't build Boost.Python&quot; problems come from people
who had to use a different tool.
</td>
</tr>
</table>
<p>

View File

@@ -0,0 +1,210 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Creating Packages</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="general_techniques.html">
<link rel="next" href="extending_wrapped_objects_in_python.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Creating Packages</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="general_techniques.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="extending_wrapped_objects_in_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
A Python package is a collection of modules that provide to the user a certain
functionality. If you're not familiar on how to create packages, a good
introduction to them is provided in the
<a href="http://www.python.org/doc/current/tut/node8.html">
Python Tutorial</a>.</p>
<p>
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
with an example.</p>
<p>
We have a C++ library that works with sounds: reading and writing various
formats, applying filters to the sound data, etc. It is named (conveniently)
<tt>sounds</tt>. Our library already has a neat C++ namespace hierarchy, like so: </p>
<code><pre>
<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></code>
<p>
We would like to present this same hierarchy to the Python user, allowing him
to write code like this:</p>
<code><pre>
<span class=identifier>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=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></pre></code>
<p>
The first step is to write the wrapping code. We have to export each module
separately with Boost.Python, like this:</p>
<code><pre>
<span class=comment>/* file core.cpp */
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>core</span><span class=special>)
{
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>core </span><span class=keyword>namespace </span><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><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>io</span><span class=special>)
{
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>io </span><span class=keyword>namespace </span><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><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>filters</span><span class=special>)
{
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>filters </span><span class=keyword>namespace </span><span class=special>*/
...
}
</span></pre></code>
<p>
Compiling these files will generate the following Python extensions:
<tt>core.pyd</tt>, <tt>io.pyd</tt> and <tt>filters.pyd</tt>.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> The extension <tt>.pyd</tt> is used for python extension modules, which
are just shared libraries. Using the default for your system, like <tt>.so</tt> for
Unix and <tt>.dll</tt> for Windows, works just as well. </td>
</tr>
</table>
<p>
Now, we create this directory structure for our Python package:</p>
<code><pre>
sounds/
__init__.py
core.pyd
filters.pyd
io.pyd
</pre></code><p>
The file <tt>__init__.py</tt> is what tells Python that the directory <tt>sounds/</tt> is
actually a Python package. It can be a empty file, but can also perform some
magic, that will be shown later. </p>
<p>
Now our package is ready. All the user has to do is put <tt>sounds</tt> into his
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000">
PYTHONPATH</a> and fire up the interpreter:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>io
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>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=literal>'file.mp3'</span><span class=special>)
&gt;&gt;&gt; </span><span class=identifier>new_sound </span><span class=special>= </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(</span><span class=identifier>sound</span><span class=special>, </span><span class=number>1.0</span><span class=special>)
</span></pre></code>
<p>
Nice heh? </p>
<p>
This is the simplest way to create hierarchies of packages, but it is not very
flexible. What if we want to add a <i>pure</i> Python function to the filters
package, for instance, one that applies 3 filters in a sound object at once?
Sure, you can do this in C++ and export it, but why not do so in Python? You
don't have to recompile the extension modules, plus it will be easier to write
it.</p>
<p>
If we want this flexibility, we will have to complicate our package hierarchy a
little. First, we will have to change the name of the extension modules:</p>
<code><pre>
<span class=comment>/* file core.cpp */
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_core</span><span class=special>)
{
...
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>core </span><span class=keyword>namespace </span><span class=special>*/
}
</span></pre></code>
<p>
Note that we added an underscore to the module name. The filename will have to
be changed to <tt>_core.pyd</tt> as well, and we do the same to the other extension modules.
Now, we change our package hierarchy like so:</p>
<code><pre>
sounds/
__init__.py
core/
__init__.py
_core.pyd
filters/
__init__.py
_filters.pyd
io/
__init__.py
_io.pyd
</pre></code><p>
Note that we created a directory for each extension module, and added a
__init__.py to each one. But if we leave it that way, the user will have to
access the functions in the core module with this syntax: </p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>core</span><span class=special>.</span><span class=identifier>_core
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>core</span><span class=special>.</span><span class=identifier>_core</span><span class=special>.</span><span class=identifier>foo</span><span class=special>(...)
</span></pre></code>
<p>
which is not what we want. But here enters the <tt>__init__.py</tt> magic: everything
that is brought to the <tt>__init__.py</tt> namespace can be accessed directly by the
user. So, all we have to do is bring the entire namespace from <tt>_core.pyd</tt>
to <tt>core/__init__.py</tt>. So add this line of code to <tt>sounds/core/__init__.py</tt>:</p>
<code><pre>
<span class=identifier>from </span><span class=identifier>_core </span><span class=identifier>import </span><span class=special>*
</span></pre></code>
<p>
We do the same for the other packages. Now the user accesses the functions and
classes in the extension modules like before:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(...)
</span></pre></code>
<p>
with the additional benefit that we can easily add pure Python functions to
any module, in a way that the user can't tell the difference between a C++
function and a Python function. Let's add a <i>pure</i> Python function,
<tt>echo_noise</tt>, to the <tt>filters</tt> package. This function applies both the
<tt>echo</tt> and <tt>noise</tt> filters in sequence in the given <tt>sound</tt> object. We
create a file named <tt>sounds/filters/echo_noise.py</tt> and code our function:</p>
<code><pre>
<span class=identifier>import </span><span class=identifier>_filters
</span><span class=identifier>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></code>
<p>
Next, we add this line to <tt>sounds/filters/__init__.py</tt>:</p>
<code><pre>
<span class=identifier>from </span><span class=identifier>echo_noise </span><span class=identifier>import </span><span class=identifier>echo_noise
</span></pre></code>
<p>
And that's it. The user now accesses this function like any other function
from the <tt>filters</tt> package:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo_noise</span><span class=special>(...)
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="general_techniques.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="extending_wrapped_objects_in_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -93,7 +93,7 @@ arguments or overloads with a common sequence of initial arguments come
into play. Another macro is provided to make this a breeze.</p>
<p>
Like <tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt>,
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> may be used to automatically create
<tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> may be used to automatically create
the thin wrappers for wrapping member functions. Let's have an example:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>george

View File

@@ -44,10 +44,9 @@ both Boost.Python's and Python's static link library.</p>
Boost.Python's static link library comes in two variants. Both are located
in Boost's <tt>/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
variants are called <tt>boost_python.lib</tt> (for release builds) and
<tt>boost_python_debug.lib</tt> (for debugging). If you can't find the
libraries, you probably haven't built Boost.Python yet. See <a
href="../../building.html">Building and Testing</a> on how to do
this.</p>
<tt>boost_python_debug.lib</tt> (for debugging). If you can't find the libraries,
you probably haven't built Boost.Python yet. See <a href="../../building.html">
Building and Testing</a> on how to do this.</p>
<p>
Python's static link library can be found in the <tt>/libs</tt> subdirectory of
your Python directory. On Windows it is called pythonXY.lib where X.Y is
@@ -88,7 +87,7 @@ Py_Finalize</a>() to stop the interpreter and release its resources.</li></ol><p
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 Dirk Gerrits<br><br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with

View File

@@ -4,6 +4,7 @@
<title>Exception Translation</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="iterators.html">
<link rel="next" href="general_techniques.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
@@ -20,7 +21,7 @@
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
<td width="20"><a href="general_techniques.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
@@ -47,7 +48,7 @@ Users may provide custom translation. Here's an example:</p>
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
<td width="20"><a href="general_techniques.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>

View File

@@ -0,0 +1,134 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Extending Wrapped Objects in Python</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="creating_packages.html">
<link rel="next" href="reducing_compiling_time.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Extending Wrapped Objects in Python</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="creating_packages.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="reducing_compiling_time.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Thanks to Python's flexibility, you can easily add new methods to a class,
even after it was already created:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=keyword>class </span><span class=identifier>C</span><span class=special>(</span><span class=identifier>object</span><span class=special>): </span><span class=identifier>pass
</span><span class=special>&gt;&gt;&gt;
&gt;&gt;&gt; </span>##<span class=identifier>a </span><span class=identifier>regular </span><span class=identifier>function
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>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=literal>'A C instance!'
</span><span class=special>&gt;&gt;&gt;
&gt;&gt;&gt; </span>##<span class=identifier>now </span><span class=identifier>we </span><span class=identifier>turn </span><span class=identifier>it </span><span class=identifier>in </span><span class=identifier>a </span><span class=identifier>member </span><span class=identifier>function
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>C</span><span class=special>.</span><span class=identifier>__str__ </span><span class=special>= </span><span class=identifier>C_str
</span><span class=special>&gt;&gt;&gt;
&gt;&gt;&gt; </span><span class=identifier>c </span><span class=special>= </span><span class=identifier>C</span><span class=special>()
&gt;&gt;&gt; </span><span class=identifier>print </span><span class=identifier>c
</span><span class=identifier>A </span><span class=identifier>C </span><span class=identifier>instance</span><span class=special>!
&gt;&gt;&gt; </span><span class=identifier>C_str</span><span class=special>(</span><span class=identifier>c</span><span class=special>)
</span><span class=identifier>A </span><span class=identifier>C </span><span class=identifier>instance</span><span class=special>!
</span></pre></code>
<p>
Yes, Python rox. <img src="theme/smiley.gif"></img></p>
<p>
We can do the same with classes that were wrapped with Boost.Python. Suppose
we have a class <tt>point</tt> in C++:</p>
<code><pre>
<span class=keyword>class </span><span class=identifier>point </span><span class=special>{...};
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>point</span><span class=special>&gt;(</span><span class=string>&quot;point&quot;</span><span class=special>)...;
}
</span></pre></code>
<p>
If we are using the technique from the previous session, <a href="creating_packages.html">
Creating Packages</a>, we can code directly into <tt>geom/__init__.py</tt>:</p>
<code><pre>
<span class=identifier>from </span><span class=identifier>_geom </span><span class=identifier>import </span><span class=special>*
</span>##<span class=identifier>a </span><span class=identifier>regular </span><span class=identifier>function
</span><span class=identifier>def </span><span class=identifier>point_str</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
</span><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>##<span class=identifier>now </span><span class=identifier>we </span><span class=identifier>turn </span><span class=identifier>it </span><span class=identifier>into </span><span class=identifier>a </span><span class=identifier>member </span><span class=identifier>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></pre></code>
<p>
<b>All</b> point instances created from C++ will also have this member function!
This technique has several advantages:</p>
<ul><li>Cut down compile times to zero for these additional functions</li><li>Reduce the memory footprint to virtually zero</li><li>Minimize the need to recompile</li><li>Rapid prototyping (you can move the code to C++ if required without changing the interface)</li></ul><p>
You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that &quot;injects&quot; methods in other classes.</p>
<code><pre>
##<span class=identifier>The </span><span class=identifier>one </span><span class=identifier>Boost</span><span class=special>.</span><span class=identifier>Python </span><span class=identifier>uses </span><span class=keyword>for </span><span class=identifier>all </span><span class=identifier>wrapped </span><span class=identifier>classes</span><span class=special>.
</span>##<span class=identifier>You </span><span class=identifier>can </span><span class=identifier>use </span><span class=identifier>here </span><span class=identifier>any </span><span class=keyword>class </span><span class=identifier>exported </span><span class=identifier>by </span><span class=identifier>Boost </span><span class=identifier>instead </span><span class=identifier>of </span><span class=string>&quot;point&quot;
</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>class </span><span class=identifier>injector</span><span class=special>(</span><span class=identifier>object</span><span class=special>):
</span><span class=keyword>class </span><span class=identifier>__metaclass__</span><span class=special>(</span><span class=identifier>BoostPythonMetaclass</span><span class=special>):
</span><span class=identifier>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>for </span><span class=identifier>b </span><span class=identifier>in </span><span class=identifier>bases</span><span class=special>:
</span><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=identifier>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>for </span><span class=identifier>k</span><span class=special>,</span><span class=identifier>v </span><span class=identifier>in </span><span class=identifier>dict</span><span class=special>.</span><span class=identifier>items</span><span class=special>():
</span><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><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>##<span class=identifier>inject </span><span class=identifier>some </span><span class=identifier>methods </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>point </span><span class=identifier>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=identifier>def </span><span class=identifier>__repr__</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
</span><span class=keyword>return </span><span class=literal>'Point(x=%s, y=%s)' </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=identifier>def </span><span class=identifier>foo</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
</span><span class=identifier>print </span><span class=literal>'foo!'
</span></pre></code>
<p>
Now let's see how it got:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=identifier>point</span><span class=special>()
</span><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>)
&gt;&gt;&gt; </span><span class=identifier>point</span><span class=special>().</span><span class=identifier>foo</span><span class=special>()
</span><span class=identifier>foo</span><span class=special>!
</span></pre></code>
<p>
Another useful idea is to replace constructors with factory functions:</p>
<code><pre>
<span class=identifier>_point </span><span class=special>= </span><span class=identifier>point
</span><span class=identifier>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>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></code>
<p>
In this simple case there is not much gained, but for constructurs with
many overloads and/or arguments this is often a great simplification, again
with virtually zero memory footprint and zero compile-time overhead for
the keyword support.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="creating_packages.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="reducing_compiling_time.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>General Techniques</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="exception_translation.html">
<link rel="next" href="creating_packages.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>General Techniques</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exception_translation.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="creating_packages.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exception_translation.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="creating_packages.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -63,9 +63,9 @@ Besides bjam, there are of course other ways to get your module built.
What's written here should not be taken as "the one and only way".
There are of course other build tools apart from [^bjam].
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the "I can't build Boost.Python" problems come from people
Take note however that the preferred build tool for Boost.Python is bjam.
There are so many ways to set up the build incorrectly. Experience shows
that 90% of the "I can't build Boost.Python" problems come from people
who had to use a different tool.
]
@@ -1010,7 +1010,7 @@ arguments or overloads with a common sequence of initial arguments come
into play. Another macro is provided to make this a breeze.
Like [^BOOST_PYTHON_FUNCTION_OVERLOADS],
[^BOOST_PYTHON_FUNCTION_OVERLOADS] may be used to automatically create
[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] may be used to automatically create
the thin wrappers for wrapping member functions. Let's have an example:
struct george
@@ -1058,7 +1058,7 @@ Notice the use of [^init<...>] and [^optional<...>] to signify the default
[page:1 Auto-Overloading]
It was mentioned in passing in the previous section that
[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_FUNCTION_OVERLOADS]
[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
can also be used for overloaded functions and member functions with a
common sequence of initial arguments. Here is an example:
@@ -1698,7 +1698,7 @@ with an example.
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)
[^sounds]. Our library already has a neat C++ namespace hierarchy, like so:
[^sounds]. Our library already has a neat C++ namespace hierarchy, like so:
sounds::core
sounds::io
@@ -1718,21 +1718,21 @@ separately with Boost.Python, like this:
{
/* export everything in the sounds::core namespace */
...
}
}
/* file io.cpp */
BOOST_PYTHON_MODULE(io)
{
/* export everything in the sounds::io namespace */
...
}
}
/* file filters.cpp */
BOOST_PYTHON_MODULE(filters)
{
/* export everything in the sounds::filters namespace */
...
}
}
Compiling these files will generate the following Python extensions:
[^core.pyd], [^io.pyd] and [^filters.pyd].
@@ -1753,7 +1753,7 @@ Now, we create this directory structure for our Python package:
The file [^__init__.py] is what tells Python that the directory [^sounds/] is
actually a Python package. It can be a empty file, but can also perform some
magic, that will be shown later.
magic, that will be shown later.
Now our package is ready. All the user has to do is put [^sounds] into his
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH] and fire up the interpreter:
@@ -1763,7 +1763,7 @@ Now our package is ready. All the user has to do is put [^sounds] into his
>>> sound = sounds.io.open('file.mp3')
>>> new_sound = sounds.filters.echo(sound, 1.0)
Nice heh?
Nice heh?
This is the simplest way to create hierarchies of packages, but it is not very
flexible. What if we want to add a ['pure] Python function to the filters
@@ -1780,7 +1780,7 @@ little. First, we will have to change the name of the extension modules:
{
...
/* export everything in the sounds::core namespace */
}
}
Note that we added an underscore to the module name. The filename will have to
be changed to [^_core.pyd] as well, and we do the same to the other extension modules.
@@ -1802,7 +1802,7 @@ Now, we change our package hierarchy like so:
Note that we created a directory for each extension module, and added a
__init__.py to each one. But if we leave it that way, the user will have to
access the functions in the core module with this syntax:
access the functions in the core module with this syntax:
>>> import sounds.core._core
>>> sounds.core._core.foo(...)
@@ -1854,7 +1854,7 @@ even after it was already created:
>>> def C_str(self): return 'A C instance!'
>>>
>>> # now we turn it in a member function
>>> C.__str__ = C_str
>>> C.__str__ = C_str
>>>
>>> c = C()
>>> print c
@@ -1874,7 +1874,7 @@ we have a class [^point] in C++:
class_<point>("point")...;
}
If we are using the technique from the previous session, [@creating_packages.html
If we are using the technique from the previous session, [@creating_packages.html
Creating Packages], we can code directly into [^geom/__init__.py]:
from _geom import *
@@ -1882,7 +1882,7 @@ Creating Packages], we can code directly into [^geom/__init__.py]:
# a regular function
def point_str(self):
return str((self.x, self.y))
# now we turn it into a member function
point.__str__ = point_str
@@ -1897,9 +1897,9 @@ This technique has several advantages:
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.
# The one Boost.Python uses for all wrapped classes.
# The one Boost.Python uses for all wrapped classes.
# You can use here any class exported by Boost instead of "point"
BoostPythonMetaclass = point.__class__
BoostPythonMetaclass = point.__class__
class injector(object):
class __metaclass__(BoostPythonMetaclass):
@@ -1946,10 +1946,10 @@ class_ definitions in multiple files:
/* file point.cpp */
#include <point.h>
#include <boost/python.hpp>
void export_point()
{
class_<point>("point")...;
class_<point>("point")...;
}
/* file triangle.cpp */
@@ -1962,11 +1962,11 @@ class_ definitions in multiple files:
}
Now you create a file [^main.cpp], which contains the [^BOOST_PYTHON_MODULE]
macro, and call the various export functions inside it.
macro, and call the various export functions inside it.
void export_point();
void export_triangle();
BOOST_PYTHON_MODULE(_geom)
{
export_point();
@@ -1984,15 +1984,15 @@ usual approach:
{
class_<point>("point")...;
class_<triangle>("triangle")...;
}
}
but the memory is kept under control.
but the memory is kept under control.
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
the compilation of a single cpp, instead of the entire wrapper code.
[blurb __note__ If you're exporting your classes with [@../../../pyste/index.html Pyste],
[blurb __note__ If you're exporting your classes with [@../../../pyste/index.html Pyste],
take a look at the [^--multiple] option, that generates the wrappers in
various files as demonstrated here.]

View File

@@ -0,0 +1,115 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Reducing Compiling Time</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="extending_wrapped_objects_in_python.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Reducing Compiling Time</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="extending_wrapped_objects_in_python.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<p>
If you have ever exported a lot of classes, you know that it takes quite a good
time to compile the Boost.Python wrappers. Plus the memory consumption can
easily become too high. If this is causing you problems, you can split the
class_ definitions in multiple files:</p>
<code><pre>
<span class=comment>/* file point.cpp */
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>&gt;
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=keyword>void </span><span class=identifier>export_point</span><span class=special>()
{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>point</span><span class=special>&gt;(</span><span class=string>&quot;point&quot;</span><span class=special>)...;
}
/* </span><span class=identifier>file </span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>cpp </span><span class=special>*/
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>&gt;
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=keyword>void </span><span class=identifier>export_triangle</span><span class=special>()
{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>triangle</span><span class=special>&gt;(</span><span class=string>&quot;triangle&quot;</span><span class=special>)...;
}
</span></pre></code>
<p>
Now you create a file <tt>main.cpp</tt>, which contains the <tt>BOOST_PYTHON_MODULE</tt>
macro, and call the various export functions inside it. </p>
<code><pre>
<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><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
{
</span><span class=identifier>export_point</span><span class=special>();
</span><span class=identifier>export_triangle</span><span class=special>();
}
</span></pre></code>
<p>
Compiling and linking together all this files produces the same result as the
usual approach:</p>
<code><pre>
<span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>&gt;
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>&gt;
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
{
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>point</span><span class=special>&gt;(</span><span class=string>&quot;point&quot;</span><span class=special>)...;
</span><span class=identifier>class_</span><span class=special>&lt;</span><span class=identifier>triangle</span><span class=special>&gt;(</span><span class=string>&quot;triangle&quot;</span><span class=special>)...;
}
</span></pre></code>
<p>
but the memory is kept under control. </p>
<p>
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
the compilation of a single cpp, instead of the entire wrapper code.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> If you're exporting your classes with <a href="../../../pyste/index.html">
Pyste</a>,
take a look at the <tt>--multiple</tt> option, that generates the wrappers in
various files as demonstrated here. </td>
</tr>
</table>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> This method is useful too if you are getting the error message
<i>&quot;fatal error C1204:Compiler limit:internal structure overflow&quot;</i> when compiling
a large source file, as explained in the <a href="../../v2/faq.html#c1204">
FAQ</a>. </td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="extending_wrapped_objects_in_python.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -145,15 +145,13 @@ previous section</a>: the aptly named <tt>object</tt>
class and it's derivatives. What we haven't seen, is that they can be
constructed from a <tt>handle</tt>. The following examples should illustrate this
fact:</p>
<code>
<pre>
<code><pre>
<span class=identifier>handle</span><span class=special>&lt;&gt; </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>&quot;__main__&quot;</span><span class=special>) ));
</span><span class=identifier>dict </span><span class=identifier>main_namespace</span><span class=special>(</span><span class=identifier>handle</span><span class=special>&lt;&gt;(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) )));
</span><span class=identifier>handle</span><span class=special>&lt;&gt;( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>&quot;result = 5 ** 2&quot;</span><span class=special>, </span><span class=identifier>Py_file_input</span><span class=special>,
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) );
</span><span class=keyword>int </span><span class=identifier>five_squared </span><span class=special>= </span><span class=identifier>extract</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;( </span><span class=identifier>main_namespace</span><span class=special>[</span><span class=string>&quot;result&quot;</span><span class=special>] );
</span></pre>
</code>
</span></pre></code>
<p>
Here we create a dictionary object for the <tt>__main__</tt> module's namespace.
Then we assign 5 squared to the result variable and read this variable from
@@ -229,7 +227,7 @@ allow_null</a> function in the same way you'd use borrowed:</p>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 Dirk Gerrits<br><br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with

View File

@@ -145,6 +145,26 @@
<a href="doc/exception_translation.html">Exception Translation</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/general_techniques.html">General Techniques</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/creating_packages.html">Creating Packages</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/extending_wrapped_objects_in_python.html">Extending Wrapped Objects in Python</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/reducing_compiling_time.html">Reducing Compiling Time</a>
</td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2002-2003 David Abrahams<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>

View File

@@ -45,7 +45,7 @@ of work got done...
<h3><a name="arity">Arbitrary Arity Support</a></h3>
I began using the <a
href="../../../preprocessor/doc/index.htm">Boost.Preprocessor</a>
href="../../../preprocessor/doc/index.html">Boost.Preprocessor</a>
metaprogramming library to generate support for functions and member
functions of arbitrary arity, which was, to say the least, quite an
adventure. The feedback cycle resulting from my foray into

View File

@@ -28,50 +28,40 @@
<h2><a name="introduction"></a>Introduction</h2>
<p>Instances of a dereferenceable type can be used like a pointer to access an lvalue.
<p>Instances of a Dereferenceable type can be used like a pointer to access an lvalue.
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
<h3><a name="Dereferenceable-concept"></a>Dereferenceable Concept</h3>
<p>In the table below, <code><b>x</b></code> denotes an object whose
type is a model of Dereferenceable.
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Requirements</b></td>
</tr>
<tr>
<td valign="top"><code>*x</code></td>
<td>An lvalue
</tr>
</table>
If <code><b>x</b></code> is not a pointer type, it also must satsify the following expression:
<p>In the table below, <code><b>T</b></code> is a model of
Dereferenceable, and <code><b>x</b></code> denotes an object of
type <code>T</code>. In addition, all pointers are Dereferenceable.
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Result</b></td>
<td><b>Operational Semantics</b></td>
</tr>
<tr>
<td valign="top"><code>x.get()</code></td>
<td><code>get_pointer(x)</code></td>
<td>convertible to <code><a href="pointee.html#pointee-spec">pointee</a>&lt;T&gt;::type*</code>
<td><code>&amp;*x</code>, or a null pointer
</tr>
<tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
29 November, 2002
18 December, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002. All Rights Reserved.</i>
Abrahams</a> 2002-2003. All Rights Reserved.</i>
<p>Permission to copy, use, modify, sell
and distribute this software is granted provided this copyright notice appears

View File

@@ -54,7 +54,7 @@ focused on reducing the support burden. In recent weeks, responding to
requests for support, espcially surrounding building the library, had
begun to impede progress on development. There was a major push to
release a stable 1.28.0 of Boost, including documentation of <a
href="../../../../tools/build/index.html">Boost.Build</a> and specific
href="../../../../tools/build/v1/build_system.htm">Boost.Build</a> and specific
<a href="../building.html">instructions</a> for building Boost.Python
v1. The documentation for Boost.Python v2 was also updated as
described <a href="#documentation">here</a>.
@@ -70,7 +70,7 @@ described <a href="#documentation">here</a>.
Martin Casado which uncovered the key mechanism required to allow
shared libraries to use functions from the Python executable. The
current solution used in Boost.Build relies on a <a
href="../../../../tools/build/gen_aix_import_file.py">Python
href="../../../../tools/build/v1/gen_aix_import_file.py">Python
Script</a> as part of the build process. This is not a problem for
Boost.Python, as Python will be available. However, the commands
issued by the script are so simple that a 100%-pure-Boost.Jam
@@ -84,8 +84,7 @@ described <a href="#documentation">here</a>.
Support for exposing C++ operators and functions as the corresponding
Python special methods was added. Thinking that the Boost.Python
<a href="../special.html#numeric">v1 interface</a> was a little too
esoteric (especially the use of
v1 interface was a little too esoteric (especially the use of
<code>left_operand&lt;...&gt;/right_operand&lt;...&gt;</code> for
asymmetric operands), I introduced a simple form of <a
href="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">expression
@@ -155,7 +154,7 @@ This forced the exposure of the <a
href="http://www.python.org/2.2/descrintro.html#property"><code>property</code></a>
interface used internally to implement the data member exposure
facility described in <a
href="Mar2002#data_members">March</a>. Properties are an
href="Mar2002.html#data_members">March</a>. Properties are an
incredibly useful idiom, so it's good to be able to provide them
at little new development cost.
@@ -212,7 +211,7 @@ Major updates were made to the following pages:
<blockquote>
<dl>
<dt><a href="call.html">call.html</a><dd> <dt><a href="updated">updated</a><dd>
<dt><a href="call.html">call.html</a><dd> <dt>updated<dd>
<dt><a href="class.html">class.html</a><dd>
<dt><a href="reference.html">reference.html</a><dd>
</dl>

View File

@@ -72,7 +72,7 @@
use the new preproccessor metaprogramming constructs and helping us to
work around buggy and slow C++ preprocessors.</p>
<p><a href="nicodemus-at-globalite.com.br">Bruno da Silva de
<p><a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
Oliveira</a> contributed the ingenious <a
href="../../pyste/index.html">Pyste</a> (&quot;Pie-Steh&quot;)
code generator.

View File

@@ -281,6 +281,7 @@ namespace boost { namespace python
// pickle support
template &lt;typename PickleSuite&gt;
self&amp; def_pickle(PickleSuite const&amp;);
self&amp; enable_pickling();
};
}}
</pre>
@@ -709,6 +710,21 @@ class_&amp; def_pickle(PickleSuite const&amp;);
checks.</dt>
</dl>
<br>
<pre>
class_&amp; enable_pickling();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Defines the <code>__reduce__</code> method and
the <code>__safe_for_unpickling__</code> attribute.
<dt><b>Returns:</b> <code>*this</code></dt>
<dt><b>Rationale:</b> Light-weight alternative to
<code>def_pickle()</code>. Enables implementation of
<a href="pickle.html">pickle support</a> from Python.</dt>
</dl>
<br>
<h3><a name="bases-spec"></a>Class template

View File

@@ -58,10 +58,25 @@
<dt><a href="#ownership">How can I wrap a function which needs to take
ownership of a raw pointer?</a></dt>
<dt><a href="#slow_compilation">Compilation takes too much time and eats too much memory!
<dt><a href="#slow_compilation">Compilation takes too much time and eats too much memory!
What can I do to make it faster?</a></dt>
<dt><a href="#packages">How do I create sub-packages using Boost.Python?</a></dt>
<dt><a href="#packages">How do I create sub-packages using Boost.Python?</a></dt>
<dt><a href="#msvcthrowbug"
>error C2064: term does not evaluate to a function taking 2 arguments</a>
</dt>
<dt><a href="#voidptr">How do I handle <tt>void *</tt> conversion?</a></dt>
<dt><a href="#custom_string"
>How can I automatically convert my custom string type to
and from a Python string?</a></dt>
<dt><a href="#topythonconversionfailed">Why is my automatic to-python conversion not being
found?</a></dt>
<dt><a href="#threadsupport">Is Boost.Python thread-aware/compatible with multiple interpreters?</a></dt>
</dl>
<hr>
@@ -87,7 +102,7 @@ And then:
<pre>
&gt;&gt;&gt; def hello(s):
... print s
... print s
...
&gt;&gt;&gt; foo(hello)
hello, world!
@@ -119,7 +134,7 @@ hello, world!
<h2><a name="dangling">I'm getting the "attempt to return dangling
reference" error. What am I doing wrong?</a></h2>
That exception is protecting you from causing a nasty crash. It usually
happens in response to some code like this:
happens in response to some code like this:
<pre>
period const&amp; get_floating_frequency() const
{
@@ -127,7 +142,7 @@ period const&amp; get_floating_frequency() const
m_self,"get_floating_frequency");
}
</pre>
And you get:
And you get:
<pre>
ReferenceError: Attempt to return dangling reference to object of type:
class period
@@ -158,7 +173,7 @@ class period
I have the choice of using copy_const_reference or
return_internal_reference. Are there considerations that would lead me
to prefer one over the other, such as size of generated code or memory
overhead?</i>
overhead?</i>
<p><b>A:</b> copy_const_reference will make an instance with storage
for one of your objects, size = base_size + 12 * sizeof(double).
@@ -180,7 +195,7 @@ class period
<ol>
<li>
Using the regular <code>class_&lt;&gt;</code> wrapper:
Using the regular <code>class_&lt;&gt;</code> wrapper:
<pre>
class_&lt;std::vector&lt;double&gt; &gt;("std_vector_double")
.def(...)
@@ -189,13 +204,13 @@ class_&lt;std::vector&lt;double&gt; &gt;("std_vector_double")
</pre>
This can be moved to a template so that several types (double, int,
long, etc.) can be wrapped with the same code. This technique is used
in the file
in the file
<blockquote>
scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h
</blockquote>
in the "scitbx" package. The file could easily be modified for
wrapping std::vector&lt;&gt; instantiations.
wrapping std::vector&lt;&gt; instantiations.
<p>This type of C++/Python binding is most suitable for containers
that may contain a large number of elements (&gt;10000).</p>
@@ -203,19 +218,19 @@ class_&lt;std::vector&lt;double&gt; &gt;("std_vector_double")
<li>
Using custom rvalue converters. Boost.Python "rvalue converters"
match function signatures such as:
match function signatures such as:
<pre>
void foo(std::vector&lt;double&gt; const&amp; array); // pass by const-reference
void foo(std::vector&lt;double&gt; array); // pass by value
</pre>
Some custom rvalue converters are implemented in the file
Some custom rvalue converters are implemented in the file
<blockquote>
scitbx/include/scitbx/boost_python/container_conversions.h
</blockquote>
This code can be used to convert from C++ container types such as
std::vector&lt;&gt; or std::list&lt;&gt; to Python tuples and vice
versa. A few simple examples can be found in the file
versa. A few simple examples can be found in the file
<blockquote>
scitbx/array_family/boost_python/regression_test_module.cpp
@@ -230,7 +245,7 @@ void foo(std::vector&lt;double&gt; array); // pass by value
rvalue converters that convert to a "math_array" type instead of tuples.
This is currently not implemented but is possible within the framework of
Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
this was posted on 2002/03/10]
this was posted on 2002/03/10]
<p>It would also be useful to also have "custom lvalue converters" such
as std::vector&lt;&gt; &lt;-&gt; Python list. These converters would
@@ -245,7 +260,7 @@ void foo(std::vector&lt;double&gt;&amp; array)
}
}
</pre>
Python:
Python:
<pre>
&gt;&gt;&gt; l = [1, 2, 3]
&gt;&gt;&gt; foo(l)
@@ -253,7 +268,7 @@ void foo(std::vector&lt;double&gt;&amp; array)
[2, 4, 6]
</pre>
Custom lvalue converters require changes to the Boost.Python core library
and are currently not available.
and are currently not available.
<p>P.S.:</p>
@@ -270,7 +285,7 @@ cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
<blockquote>
<b>Q:</b> <i>I get this error message when compiling a large source
file. What can I do?</i>
file. What can I do?</i>
<p><b>A:</b> You have two choices:</p>
@@ -278,7 +293,7 @@ cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
<li>Upgrade your compiler (preferred)</li>
<li>
Break your source file up into multiple translation units.
Break your source file up into multiple translation units.
<p><code><b>my_module.cpp</b></code>:</p>
<pre>
@@ -292,7 +307,7 @@ BOOST_PYTHON_MODULE(my_module)
more_of_my_module();
}
</pre>
<code><b>more_of_my_module.cpp</b></code>:
<code><b>more_of_my_module.cpp</b></code>:
<pre>
void more_of_my_module()
{
@@ -306,7 +321,7 @@ void more_of_my_module()
can always pass a reference to the <code>class_</code> object to a
function in another source file, and call some of its member
functions (e.g. <code>.def(...)</code>) in the auxilliary source
file:
file:
<p><code><b>more_of_my_class.cpp</b></code>:</p>
<pre>
@@ -337,7 +352,7 @@ void more_of_my_class(class&lt;my_class&gt;&amp; x)
library that is under test, given that python code is minimal and
boost::python either works or it doesn't. (ie. While errors can occur
when the wrapping method is invalid, most errors are caught by the
compiler ;-).
compiler ;-).
<p>The basic steps required to initiate a gdb session to debug a c++
library via python are shown here. Note, however that you should start
@@ -368,20 +383,69 @@ Current language: auto; currently c++
solid and "just works" without requiring any special tricks from the
user.</p>
<p>Unfortunately for Cygwin and MinGW users, as of this writing gdb on
Windows has a very hard time dealing with shared libraries, which could
make Greg's approach next to useless for you. My best advice for you is
to use Metrowerks C++ for compiler conformance and Microsoft Visual
Studio as a debugger when you need one.</p>
<p>Raoul Gough has provided the following for gdb on Windows:</p>
<blockquote>
<p>gdb support for Windows DLLs has improved lately, so it is
now possible to debug Python extensions using a few
tricks. Firstly, you will need an up-to-date gdb with support
for minimal symbol extraction from a DLL. Any gdb from version 6
onwards, or Cygwin gdb-20030214-1 and onwards should do. A
suitable release will have a section in the gdb.info file under
Configuration &ndash; Native &ndash; Cygwin Native &ndash;
Non-debug DLL symbols. Refer to that info section for more
details of the procedures outlined here.</p>
<p>Secondly, it seems necessary to set a breakpoint in the
Python interpreter, rather than using ^C to break execution. A
good place to set this breakpoint is PyOS_Readline, which will
stop execution immediately before reading each interactive
Python command. You have to let Python start once under the
debugger, so that it loads its own DLL, before you can set the
breakpoint:</p>
<p>
<pre>
$ gdb python
GNU gdb 2003-09-02-cvs (cygwin-special)
[...]
(gdb) run
Starting program: /cygdrive/c/Python22/python.exe
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; ^Z
Program exited normally.
(gdb) break *&amp;PyOS_Readline
Breakpoint 1 at 0x1e04eff0
(gdb) run
Starting program: /cygdrive/c/Python22/python.exe
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
from /cygdrive/c/WINNT/system32/python22.dll
(gdb) cont
Continuing.
&gt;&gt;&gt; from my_ext import *
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
from /cygdrive/c/WINNT/system32/python22.dll
(gdb) # my_ext now loaded (with any debugging symbols it contains)
</pre>
</blockquote>
<h3>Debugging extensions through Boost.Build</h3>
If you are launching your extension module tests with <a href=
"../../../tools/build">Boost.Build</a> using the
"../../../../tools/build/v1/build_system.htm">Boost.Build</a> using the
<code>boost-python-runtest</code> rule, you can ask it to launch your
debugger for you by adding "-sPYTHON_LAUNCH=<i>debugger</i>" to your bjam
command-line:
debugger for you by adding "--debugger=<i>debugger</i>" to your bjam
command-line:
<pre>
bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
</pre>
It can also be extremely useful to add the <code>-d+2</code> option when
@@ -389,7 +453,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
commands it uses to invoke it. This will invariably involve setting up
PYTHONPATH and other important environment variables such as
LD_LIBRARY_PATH which may be needed by your debugger in order to get
things to work right.
things to work right.
<hr>
<h2><a name="imul"></a>Why doesn't my <code>*=</code> operator work?</h2>
@@ -400,7 +464,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
<i>operator. It always tells me "can't multiply sequence with non int
type". If I use</i> <code>p1.__imul__(p2)</code> <i>instead of</i>
<code>p1 *= p2</code><i>, it successfully executes my code. What's
wrong with me?</i>
wrong with me?</i>
<p><b>A:</b> There's nothing wrong with you. This is a bug in Python
2.2. You can see the same effect in Pure Python (you can learn a lot
@@ -421,24 +485,54 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
<h2><a name="macosx"></a>Does Boost.Python work with Mac OS X?</h2>
<blockquote>
<p>The short answer: as of January 2003, unfortunately not.</p>
It is known to work under 10.2.8 and 10.3 using
Apple's gcc 3.3 compiler:
<pre>gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)</pre>
Under 10.2.8 get the August 2003 gcc update (free at
<a href="http://connect.apple.com/">http://connect.apple.com/</a>).
Under 10.3 get the Xcode Tools v1.0 (also free).
<p>
Python 2.3 is required. The Python that ships with 10.3 is
fine. Under 10.2.8 use these commands to install Python
as a framework:
<pre>./configure --enable-framework
make
make frameworkinstall</pre>
The last command requires root privileges because the target
directory is
<tt>/Library/Frameworks/Python.framework/Versions/2.3</tt>.
However, the installation does not interfere with the Python
version that ships with 10.2.8.
<p>
It is also crucial to increase the <tt>stacksize</tt> before
starting compilations, e.g.:
<pre>limit stacksize 8192k</pre>
If the <tt>stacksize</tt> is too small the build might crash with
internal compiler errors.
<p>
Sometimes Apple's compiler exhibits a bug by printing an error
like the following while compiling a
<tt>boost::python::class_&lt;your_type&gt;</tt>
template instantiation:
<pre>.../inheritance.hpp:44: error: cannot
dynamic_cast `p' (of type `struct cctbx::boost_python::&lt;unnamed&gt;::add_pair*
') to type `void*' (source type is not polymorphic)</pre>
<p>The longer answer: using Mac OS 10.2.3 with the December Developer's
Kit, Python 2.3a1, and bjam's darwin-tools.jam, Boost.Python compiles
fine, including the examples. However, there are problems at runtime
(see <a href=
"http://mail.python.org/pipermail/c++-sig/2003-January/003267.html">http://mail.python.org/pipermail/c++-sig/2003-January/003267.html</a>).
Solutions are currently unknown.</p>
We do not know a general workaround, but if the definition of
<tt>your_type</tt> can be modified the following was found
to work in all cases encountered so far:<pre>struct your_type
{
// before defining any member data
#if defined(__MACH__) &amp;&amp; defined(__APPLE_CC__) &amp;&amp; __APPLE_CC__ == 1493
bool dummy_;
#endif
// now your member data, e.g.
double x;
int j;
// etc.
};</pre>
<p>It is known that under certain circumstances objects are
double-destructed. See <a href=
"http://mail.python.org/pipermail/c++-sig/2003-January/003278.html">http://mail.python.org/pipermail/c++-sig/2003-January/003278.html</a>
for details. It is not clear however if this problem is related to the
Boost.Python runtime issues.</p>
</blockquote>
<hr>
<h2><a name="xref">How can I find the existing PyObject that holds a C++
object?</a></h2>
@@ -450,7 +544,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
with virtual functions. If you make a wrapper class with an initial
PyObject* constructor argument and store that PyObject* as "self", you
can get back to it by casting down to that wrapper type in a thin wrapper
function. For example:
function. For example:
<pre>
class X { X(int); virtual ~X(); ... };
X* f(); // known to return Xs that are managed by Python objects
@@ -483,7 +577,7 @@ class_&lt;X,X_wrap&gt;("X", init&lt;int&gt;())
runtime check that it's valid. This approach also only works if the
<code>X</code> object was constructed from Python, because
<code>X</code>s constructed from C++ are of course never
<code>X_wrap</code> objects.
<code>X_wrap</code> objects.
<p>Another approach to this requires you to change your C++ code a bit;
if that's an option for you it might be a better way to go. work we've
@@ -502,11 +596,13 @@ class_&lt;X,X_wrap&gt;("X", init&lt;int&gt;())
its containing Python object, and you could have your f_wrap function
look in that mapping to get the Python object out.</p>
<hr>
<h2><a name="ownership">How can I wrap a function which needs to take
ownership of a raw pointer?</a></h2>
<blockquote>
<i>Part of an API that I'm wrapping goes something like this:</i>
<i>Part of an API that I'm wrapping goes something like this:</i>
<pre>
struct A {}; struct B { void add( A* ); }
where B::add() takes ownership of the pointer passed to it.
@@ -517,9 +613,9 @@ where B::add() takes ownership of the pointer passed to it.
a = mod.A()
b = mod.B()
b.add( a )
del a
del a
del b
# python interpreter crashes
# python interpreter crashes
# later due to memory corruption.
</pre>
@@ -530,13 +626,13 @@ del b
<p><i>--Bruce Lowery</i></p>
</blockquote>
Yes: Make sure the C++ object is held by auto_ptr:
Yes: Make sure the C++ object is held by auto_ptr:
<pre>
class_&lt;A, std::auto_ptr&lt;A&gt; &gt;("A")
...
;
</pre>
Then make a thin wrapper function which takes an auto_ptr parameter:
Then make a thin wrapper function which takes an auto_ptr parameter:
<pre>
void b_insert(B&amp; b, std::auto_ptr&lt;A&gt; a)
{
@@ -547,26 +643,237 @@ void b_insert(B&amp; b, std::auto_ptr&lt;A&gt; a)
Wrap that as B.add. Note that pointers returned via <code><a href=
"manage_new_object.html#manage_new_object-spec">manage_new_object</a></code>
will also be held by <code>auto_ptr</code>, so this transfer-of-ownership
will also work correctly.
will also work correctly.
<hr>
<h2><a name="slow_compilation">Compilation takes too much time and eats too
much memory! What can I do to make it faster?</a></h2>
much memory! What can I do to make it faster?</a></h2>
<p>
Please refer to the <a href="../tutorial/doc/reducing_compiling_time.html">Techniques</a>
section in the tutorial.
Please refer to the <a href="../tutorial/doc/reducing_compiling_time.html"
>Reducing Compiling Time</a> section in the tutorial.
</p>
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
<hr>
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
<p>
In the <a href="../tutorial/doc/creating_packages.html">Techniques</a>
section of the tutorial this topic is explored.
Please refer to the <a href="../tutorial/doc/creating_packages.html"
>Creating Packages</a> section in the tutorial.
</p>
<hr>
<h2><a name="msvcthrowbug"></a>error C2064: term does
not evaluate to a function taking 2 arguments</h2>
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue
an error message like the following it is most likely due to a bug
in the compiler:
<pre>boost\boost\python\detail\invoke.hpp(76):
error C2064: term does not evaluate to a function taking 2 arguments"</pre>
This message is triggered by code like the following:
<pre>#include &lt;boost/python.hpp&gt;
using namespace boost::python;
class FXThread
{
public:
bool setAutoDelete(bool doso) throw();
};
void Export_FXThread()
{
class_< FXThread >("FXThread")
.def("setAutoDelete", &amp;FXThread::setAutoDelete)
;
}
</pre>
The bug is related to the <code>throw()</code> modifier.
As a workaround cast off the modifier. E.g.:
<pre>
.def("setAutoDelete", (bool (FXThread::*)(bool)) &amp;FXThread::setAutoDelete)</pre>
<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_; // Deliberately do not define
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void_);
void *foo(int par1, void *par2);
void_ *foo_wrapper(int par1, void_ *par2)
{
return (void_ *) foo(par1, par2);
}
...
BOOST_PYTHON_MODULE(bar)
{
def("foo", &amp;foo_wrapper);
}</pre>
<hr>
<h2><a name="custom_string"></a>How can I automatically
convert my custom string type to and from a Python string?</h2>
<font size="-1"><i>Ralf W. Grosse-Kunstleve provides these
notes:</i></font><p>
Below is a small, self-contained demo extension module that shows
how to do this. Here is the corresponding trivial test:
<pre>import custom_string
assert custom_string.hello() == "Hello world."
assert custom_string.size("california") == 10</pre>
If you look at the code you will find:
<ul>
<li>A custom <tt>to_python</tt> converter (easy):
<tt>custom_string_to_python_str</tt>
<li>A custom lvalue converter (needs more code):
<tt>custom_string_from_python_str</tt>
</ul>
The custom converters are registered in the global Boost.Python
registry near the top of the module initialization function. Once
flow control has passed through the registration code the automatic
conversions from and to Python strings will work in any module
imported in the same process.
<pre>#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/to_python_converter.hpp&gt;
namespace sandbox { namespace {
class custom_string
{
public:
custom_string() {}
custom_string(std::string const&amp; value) : value_(value) {}
std::string const&amp; value() const { return value_; }
private:
std::string value_;
};
struct custom_string_to_python_str
{
static PyObject* convert(custom_string const&amp; s)
{
return boost::python::incref(boost::python::object(s.value()).ptr());
}
};
struct custom_string_from_python_str
{
custom_string_from_python_str()
{
boost::python::converter::registry::push_back(
&amp;convertible,
&amp;construct,
boost::python::type_id&lt;custom_string&gt;());
}
static void* convertible(PyObject* obj_ptr)
{
if (!PyString_Check(obj_ptr)) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
const char* value = PyString_AsString(obj_ptr);
if (value == 0) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage&lt;custom_string&gt;*)
data)-&gt;storage.bytes;
new (storage) custom_string(value);
data-&gt;convertible = storage;
}
};
custom_string hello() { return custom_string(&quot;Hello world.&quot;); }
std::size_t size(custom_string const&amp; s) { return s.value().size(); }
void init_module()
{
using namespace boost::python;
boost::python::to_python_converter&lt;
custom_string,
custom_string_to_python_str&gt;();
custom_string_from_python_str();
def(&quot;hello&quot;, hello);
def(&quot;size&quot;, size);
}
}} // namespace sandbox::&lt;anonymous&gt;
BOOST_PYTHON_MODULE(custom_string)
{
sandbox::init_module();
}</pre>
<hr>
<h2><a name="topythonconversionfailed"></a
>Why is my automatic to-python conversion not being found?</h2>
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
If you define custom converters similar to the ones
shown above the <tt>def_readonly()</tt> and <tt>def_readwrite()</tt>
member functions provided by <tt>boost::python::class_</tt> for
direct access to your member data will not work as expected.
This is because <tt>def_readonly("bar",&nbsp;&amp;foo::bar)</tt> is
equivalent to:
<pre>.add_property("bar", make_getter(&amp;foo::bar, return_internal_reference()))</pre>
Similarly, <tt>def_readwrite("bar",&nbsp;&amp;foo::bar)</tt> is
equivalent to:
<pre>.add_property("bar", make_getter(&amp;foo::bar, return_internal_reference()),
make_setter(&amp;foo::bar, return_internal_reference())</pre>
In order to define return value policies compatible with the
custom conversions replace <tt>def_readonly()</tt> and
<tt>def_readwrite()</tt> by <tt>add_property()</tt>. E.g.:
<pre>.add_property("bar", make_getter(&amp;foo::bar, return_value_policy&lt;return_by_value&gt;()),
make_setter(&amp;foo::bar, return_value_policy&lt;return_by_value&gt;()))</pre>
<hr>
<h2><a name="threadsupport"></a
>Is Boost.Python thread-aware/compatible with multiple interpreters?</h2>
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
The quick answer to this is: no.</p>
<p>
The longer answer is that it can be patched to be so, but it's
complex. You will need to add custom lock/unlock wrapping of every
time your code enters Boost.Python (particularly every virtual
function override) plus heavily modify
<tt>boost/python/detail/invoke.hpp</tt> with custom unlock/lock
wrapping of every time Boost.Python enters your code. You must
furthermore take care to <i>not</i> unlock/lock when Boost.Python
is invoking iterator changes via <tt>invoke.hpp</tt>.</p>
<p>
There is a patched <tt>invoke.hpp</tt> posted on the C++-SIG
mailing list archives and you can find a real implementation of all
the machinery necessary to fully implement this in the TnFOX
project at <a href="http://sourceforge.net/projects/tnfox/"> this
SourceForge project location</a>.</p>
<hr>
<p>Revised
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
18 March, 2003
28 January, 2004
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
@@ -575,4 +882,3 @@ void b_insert(B&amp; b, std::auto_ptr&lt;A&gt; a)
Rights Reserved.</i></p>
</body>
</html>

View File

@@ -71,9 +71,8 @@ namespace boost { namespace python
{
template &lt;class T&gt;
struct from_python : private <a href=
"../../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// from_python&lt;T&gt; meets the <a href=
"NonCopyable.html">NonCopyable</a> requirements
"../../../utility/utility.htm#Class_noncopyable">boost::noncopyable</a> // Exposition only.
// from_python&lt;T&gt; meets the NonCopyable requirements
{
from_python(PyObject*);
bool convertible() const;

View File

@@ -278,7 +278,7 @@
std::vector interface]) classes (currently, this is the only predefined
suite available). It provides all the policies required by the
<tt>indexing_suite</tt>.
</p>
</p>
<p>
Example usage:
</p>
@@ -300,16 +300,16 @@
<h2>
<a name="indexing_suite_class"></a>indexing_suite class
</h2>
<h3>
Class template<br>
<tt>indexing_suite&lt;<br>
class <font color="#007F00">Container</font><br>
, class <font color="#007F00">DerivedPolicies<br></font></tt> <tt>,
bool <font color="#007F00">NoProxy</font><br>
, bool <font color="#007F00">NoProxy</font>,<br>
, class <font color="#007F00">Element</font><br>
, class <font color="#007F00">Key</font><br>
, class <font color="#007F00">Index</font></tt>
<h3>
<br>
<tt>indexing_suite&lt;<br>
class Container<br>
, class DerivedPolicies<font color="#007F00"><br>
</font></tt> <tt>,
bool NoProxy<br>
, class Element<br>
, class Key<br>
, class Index</tt>
</h3>
<table width="100%" border="1">
<tr>

View File

@@ -97,7 +97,7 @@
<pre>
namespace boost { namespace python
{
class instance_holder : <a href="../../../utility/utility.htm#Class noncopyable">noncopyable</a>
class instance_holder : <a href="../../../utility/utility.htm#Class_noncopyable">noncopyable</a>
{
public:
// destructor

View File

@@ -99,7 +99,7 @@ template &lt;class F, class Policies, class Keywords, class Signature&gt;
arguments of the resulting function.
<li>If <code>Signature</code>
is supplied, it should be an instance of an <a
href="../../mpl/doc/ref/Sequence.html">MPL front-extensible
href="../../../mpl/doc/ref/Sequence.html">MPL front-extensible
sequence</a> representing the function's return type followed by
its argument types. Pass a <code>Signature</code> when wrapping
function object types whose signatures can't be deduced, or when
@@ -135,7 +135,7 @@ template &lt;class ArgList, class Generator, class Policies&gt;
<dt><b>Requires:</b> <code>T</code> is a class type.
<code>Policies</code> is a model of <a href=
"CallPolicies.html">CallPolicies</a>. <code>ArgList</code> is an <a
href="../../../mpl/doc/Sequences.html">MPL sequence</a> of C++ argument
href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a> of C++ argument
types (<i>A1,&nbsp;A2,...&nbsp;AN</i>) such that if
<code>a1,&nbsp;a2</code>...&nbsp;<code>aN</code> are objects of type
<i>A1,&nbsp;A2,...&nbsp;AN</i> respectively, the expression <code>new

View File

@@ -208,16 +208,19 @@
<p><a name="slice_nil-spec"></a></p>
<pre>
enum slice_nil { _ };
class slice_nil;
static const _ = slice_nil();
</pre>
A type that can be used to get the effect of leaving out an index in a
Python slice expression:
<pre>
&gt;&gt;&gt; x[:-1]
&gt;&gt;&gt; x[::-1]
</pre>
C++ equivalent:
<pre>
x.slice(_,-1)
x[slice(_,_,-1)]
</pre>
<h2><a name="classes"></a>Classes</h2>

View File

@@ -281,13 +281,51 @@ is not empty.
</ul>
<hr>
<h2>Light-weight alternative: pickle support implemented in Python</h2>
&copy; Copyright Ralf W. Grosse-Kunstleve 20012-2002. Permission to copy,
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
for implementing pickle support. First we direct Boost.Python via
the <tt>class_::enable_pickling()</tt> member function to define only
the basic attributes required for pickling:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ...
.enable_pickling()
// ...
</pre>
This enables the standard Python pickle interface as described
in the Python documentation. By &quot;injecting&quot; a
<tt>__getinitargs__</tt> method into the definition of the wrapped
class we make all instances pickleable:
<pre>
# import the wrapped world class
from pickle4_ext import world
# definition of __getinitargs__
def world_getinitargs(self):
return (self.get_country(),)
# now inject __getinitargs__ (Python is a dynamic language!)
world.__getinitargs__ = world_getinitargs
</pre>
See also the
<a href="../tutorial/doc/extending_wrapped_objects_in_python.html"
>tutorial section</a> on injecting additional methods from Python.
<hr>
&copy; Copyright Ralf W. Grosse-Kunstleve 2001-2004. Permission to copy,
use, modify, sell and distribute this document is granted provided this
copyright notice appears in all copies. This document is provided "as
is" without express or implied warranty, and with no claim as to its
suitability for any purpose.
<p>
Updated: Aug 2002.
Updated: Feb 2004.
</div>

View File

@@ -27,8 +27,15 @@
</tr>
</table>
<hr>
<b>Boost.Python</b> has been successfully tested on the following
platforms and compilers:
Please see
our <a
href="http://boost.sourceforge.net/regression-logs">regression
logs</a> for up-to-date information. Note that logs not marked
otherwise reflect the CVS state, not the condition of the release.
<p>
Earlier versions of <b>Boost.Python</b> have been successfully
tested on the following platforms and compilers.
<dl class="page-index">
<dt>Unix Platforms:</dt>

View File

@@ -357,6 +357,19 @@
</dd>
</dl>
</dd>
<dt><a href="slice.html">slice.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href="slice.html#classes">Classes</a></dt>
<dd>
<dl class="index">
<dt><a href="slice.html#slice-spec">slice</a></dt>
</dl>
</dd>
</dl>
</dd>
</dl>
<h2><a name="invocation">Function Invocation and Creation</a></h2>

View File

@@ -58,10 +58,9 @@
void register_ptr_to_python()
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>P</code> is the type of the smart pointer,
for example <code>smart_ptr&lt;X&gt;</code>.
<dt><b>Requires:</b> <code>P</code> is <a href="Dereferenceable.html#Dereferenceable-concept">Dereferenceable</a>.
</dt>
<dt><b>Effects:</b> Allows conversions to-python of <code>smart_ptr&lt;X&gt;</code>
<dt><b>Effects:</b> Allows conversions to-python of <code>P</code>
instances.
</dt>
</dl>

View File

@@ -86,7 +86,7 @@
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a></td>
<td>A model of <a href=
"ResultConverterGenerator.html">ResultConverterGenerator</a>.</td>
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
</tr>
<tr>

241
doc/v2/slice.html Normal file
View File

@@ -0,0 +1,241 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<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">
<title>Boost.Python - &lt;boost/python/slice.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%"
summary="header">
<tbody>
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;boost/python/slice.hpp&gt;</h2>
</td>
</tr>
</tbody>
</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="#slice-spec">Class <code>slice</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#slice-spec-synopsis">Class <code>slice</code>
synopsis</a></dt>
<dt><a href="#slice-spec-ctors">Class <code>slice</code>
constructors</a></dt>
<dt><a href="#slice-spec-observers">Class <code>slice</code>
observer functions</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Exposes a <a href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a>
for the Python <a
href="http://www.python.org/doc/2.3.3/api/slice-objects.html">slice</a>
type.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-spec"></a>Class <code>slice</code></h3>
<p>Exposes the extended slicing protocol by wrapping the built-in slice
type. The semantics of the constructors and member functions defined
below can be fully understood by reading the <a
href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
definition. Since <code>slice</code> is publicly derived from <code><a
href="object.html#object-spec">object</a></code>, the public object
interface applies to <code>slice</code> instances as well.<br>
</p>
<h4><a name="slice-spec-synopsis"></a>Class <code>slice</code> synopsis</h4>
<pre>
namespace boost { namespace python
{
class slice : public object
{
public:
slice(); // create an empty slice, equivalent to [::]
template &lt;typename Int1, typename Int2&gt;
slice(Int1 start, Int2 stop);
template &lt;typename Int1, typename Int2, typename Int3&gt;
slice(Int1 start, Int2 stop, Int3 step);
// Access the parameters this slice was created with.
object start();
object stop();
object step();
// The return type of slice::get_indicies()
template &lt;typename RandomAccessIterator&gt;
struct range
{
RandomAccessIterator start;
RandomAccessIterator stop;
int step;
};
template &lt;typename RandomAccessIterator&gt;
range&lt;RandomAccessIterator&gt;
get_indicies(
RandomAccessIterator const&amp; begin,
RandomAccessIterator const&amp; end);
};
}}
</pre>
<h4><a name="slice-spec-ctors"></a>Class <code>slice</code>
constructors<br>
</h4>
<pre>slice();<br></pre>
<dl class="function-semantics">
<dt><b>Effects:</b> constructs a <code>slice</code> with default stop, start, and
step values.&nbsp; Equivalent to the slice object created by the Python
expression <code>base[::].</code></dt>
<dt><b>Throws:</b> nothing.</dt>
</dl>
<pre>
template &lt;typename Int1, typename Int2&gt;
slice(Int1 start, Int2 stop);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>start</code>, <code>stop</code>, and <code>step</code>
are of type <code>slice_nil</code> or convertible to type <code>object</code>.</dt>
<dt><b>Effects:</b> constructs a new slice with default step value
and the provided start and stop values.&nbsp; Equivalent to the slice
object
created by the built-in Python function <code><a
href="http://www.python.org/doc/current/lib/built-in-funcs.html#12h-62">slice(start,stop)</a></code>,
or the Python expression <code>base[start:stop]</code>.</dt>
<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 <code>object</code>.</dt>
</dl>
<pre>
template &lt;typename Int1, typename Int2, typename Int3&gt;
slice(Int1 start, Int2 stop, Int3 step);
</pre>
<dt><b>Requires:</b> <code>start</code>, <code>stop</code>, and <code>step</code> are integers, <code>slice_nil</code>, or convertible to type <code>object</code>.</dt>
<dt><b>Effects:</b> constructs a new slice with start stop and step
values.&nbsp; Equivalent to the slice object created
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>,
or 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>
exception if no conversion is possible from the arguments to type
object.</dt>
<h4><a name="slice-spec-observers"></a>Class <code>slice</code>
observer functions<br>
</h4>
<pre>
object slice::start();
object slice::stop();
object slice::step();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> None.</dt>
<dt><b>Throws:</b> nothing.</dt>
<dt><b>Returns:</b>the parameter that
the slice was created with.&nbsp;If the parameter was omitted or
slice_nil was used when the slice was created, than that parameter will
be a reference to PyNone and compare equal to a default-constructed
object.&nbsp;In principal, any object may be used when creating a
slice object, but in practice they are usually integers.</dt>
</dl>
<br>
<pre>
template &lt;typename RandomAccessIterator&gt;
slice::range&lt;RandomAccessIterator&gt;
slice::get_indicies(
RandomAccessIterator const&amp; begin, RandomAccessIterator const&amp; end);
</pre>
<dl class="function-semantics">
<dt><b>Arguments:</b> A pair of STL-conforming Random Access
Iterators that form a half-open range.</dt>
<dt><b>Effects:</b> Create a RandomAccessIterator pair that defines a
fully-closed range within the [begin,end) range of its arguments.&nbsp;
This function translates this slice's indicies while accounting for the
effects of any PyNone or negative indicies, and non-singular step sizes.</dt>
<dt><b>Returns:</b> a slice::range
that has been initialized with a non-zero value of step and a pair of
RandomAccessIterators that point within the range of this functions
arguments and define a closed interval.</dt>
<dt><b>Throws:</b> <a href="definitions.html#raise">Raises</a> a Python <code>TypeError</code> exception if any of this slice's arguments
are neither references to <code>PyNone</code> nor convertible to <code>int</code>.&nbsp; Throws
<code>std::invalid_argument</code> if the resulting range would be empty.&nbsp; You
should always wrap calls to <code>slice::get_indicies()</code>
within <code>try { ...; } catch (std::invalid_argument) {}</code> to
handle this case and take appropriate action.</dt>
<dt><b>Rationale</b>: closed-interval: If
an open interval were used, then for step
size other than 1, the required state for the end iterator would point
beyond the one-past-the-end position or before the beginning of the
specified range.<br>
exceptions on empty slice: It is impossible to define a closed interval
over an empty range, so some other form of error checking would have to
be used to prevent undefined behavior.&nbsp;In the case where the
exception is not caught, it will simply be translated to Python by the
default exception handling mechanisms. </dt>
</dl>
<h2><a name="examples"></a><b>Examples</b></h2>
<pre>
using namespace boost::python;
// Perform an extended slice of a Python list.
// Warning: extended slicing was not supported for built-in types prior
// to Python 2.3
list odd_elements(list l)
{
return l[slice(_,_,2)];
}
// Perform a multidimensional rich slice of a Numeric.array
numeric::array even_columns(numeric::array arr)
{
// select every other column, starting with the second, of a 2-D array.
// Equivalent to "return arr[:, 1::2]" in Python.
return arr[make_tuple( slice(), slice(1,_,2))];
}
// Perform a summation over a slice of a std::vector.
double partial_sum(std::vector&lt;double&gt; const&amp; Foo, slice index)
{
slice::range&lt;std::vector&lt;double&gt;::const_iterator&gt; bounds;
try {
bounds = index.get_indicies&lt;&gt;(Foo.begin(), Foo.end());
}
catch (std::invalid_argument) {
return 0.0;
}
double sum = 0.0;
while (bounds.start != bounds.end) {
sum += *bounds.start;
std::advance( bounds.start, bounds.step);
}
sum += *bounds.start;
return sum;
}
</pre>
<p>Revised 07 Febuary, 2004</p>
<p><i>&copy; Copyright <a
href="mailto:jbrandmeyer@users.sourceforge.net">Jonathan Brandmeyer</a>,
2004.&nbsp; Modification, copying and redistribution of this document
is permitted under the terms and conditions of the Boost Software
License, version 1.0.<br>
</i></p>
</body>
</html>

View File

@@ -60,8 +60,8 @@ namespace boost { namespace python
template &lt;class T&gt;
struct to_python_value
{
typedef typename <a href="../../../type_traits/index.htm#transformations">add_reference</a>&lt;
typename <a href="../../../type_traits/index.htm#transformations">add_const</a>&lt;T&gt;::type
typedef typename <a href="../../../type_traits/index.html#transformations">add_reference</a>&lt;
typename <a href="../../../type_traits/index.html#transformations">add_const</a>&lt;T&gt;::type
&gt;::type argument_type;
static bool convertible();

View File

@@ -1,6 +1,6 @@
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
# and conditions of use.
# Edit this path to point at the tools/build subdirectory of your
# Edit this path to point at the tools/build/v1 subdirectory of your
# Boost installation. Absolute paths work, too.
boost-build ../../../tools/build ;
boost-build ../../../tools/build/v1 ;

View File

@@ -32,10 +32,12 @@
namespace boost { namespace python {
typedef detail::keywords<1> arg;
namespace detail
{
template <std::size_t nkeywords>
struct keywords
struct keywords_base
{
BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords);
@@ -44,18 +46,61 @@ namespace detail
return keyword_range(elements, elements + nkeywords);
}
keywords<nkeywords+1> operator,(const keywords<1> &k) const
{
python::detail::keywords<size+1> res;
std::copy(elements, elements+size, res.elements);
res.elements[size] = k.elements[0];
return res;
}
keywords<nkeywords+1> operator,(const char *name) const;
keyword elements[nkeywords];
keywords<nkeywords+1>
operator,(arg const &k) const;
keywords<nkeywords + 1>
operator,(char const *name) const;
};
template <std::size_t nkeywords>
struct keywords : keywords_base<nkeywords>
{
};
template <>
struct keywords<1> : keywords_base<1>
{
explicit keywords(char const *name)
{
elements[0].name = name;
}
template <class T>
arg& operator=(T const& value)
{
object z(value);
elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
return *this;
}
operator detail::keyword const&() const
{
return elements[0];
}
};
template <std::size_t nkeywords>
inline
keywords<nkeywords+1>
keywords_base<nkeywords>::operator,(arg const &k) const
{
keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this);
python::detail::keywords<nkeywords+1> res;
std::copy(l.elements, l.elements+nkeywords, res.elements);
res.elements[nkeywords] = k.elements[0];
return res;
}
template <std::size_t nkeywords>
inline
keywords<nkeywords + 1>
keywords_base<nkeywords>::operator,(char const *name) const
{
return this->operator,(python::arg(name));
}
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
@@ -108,39 +153,9 @@ namespace detail
# endif
}
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730
class old_edg_workaround_for_arg { friend class arg; };
#endif
struct arg : detail::keywords<1>
{
explicit arg(char const *name)
{
elements[0].name = name;
}
template <class T>
arg& operator=(T const& value)
{
object z(value);
elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
return *this;
}
operator detail::keyword const&() const
{
return elements[0];
}
};
namespace detail
{
template <std::size_t nkeywords>
inline keywords<nkeywords + 1>
keywords<nkeywords>::operator,(const char *name) const
{
return this->operator,(arg(name));
}
inline detail::keywords<1> args(char const* name)
{
return detail::keywords<1>(name);
}
# define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n;
@@ -151,7 +166,7 @@ inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name))
BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _) \
return result; \
}
# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
# define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY)
# include BOOST_PP_LOCAL_ITERATE()
}} // namespace boost::python

View File

@@ -40,7 +40,10 @@ namespace boost { namespace python {
# endif // CALL_DWA2002411_HPP
#elif BOOST_PP_ITERATION_DEPTH() == 1
# line BOOST_PP_LINE(__LINE__, call.hpp)
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call.hpp)
# endif
# define N BOOST_PP_ITERATION()

View File

@@ -39,7 +39,10 @@ namespace boost { namespace python {
# endif // CALL_METHOD_DWA2002411_HPP
#elif BOOST_PP_ITERATION_DEPTH() == 1
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
# endif
# define N BOOST_PP_ITERATION()

View File

@@ -47,8 +47,14 @@
# include <boost/utility.hpp>
# include <boost/detail/workaround.hpp>
# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) || BOOST_WORKAROUND(__GNUC__, < 3)
# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \
/* pro9 reintroduced the bug */ \
|| (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) \
|| BOOST_WORKAROUND(__GNUC__, < 3)
# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
# endif
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
@@ -127,7 +133,6 @@ namespace detail
register_wrapper_class_impl((Held*)0, (T*)0, 0);
}
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
template <class T>
struct is_data_member_pointer
: mpl::and_<
@@ -135,15 +140,17 @@ namespace detail
, mpl::not_<is_member_function_pointer<T> >
>
{};
# define BOOST_PYTHON_DATA_MEMBER_HELPER , detail::is_data_member_pointer<D>()
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
# define BOOST_PYTHON_DATA_MEMBER_HELPER , 0
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
# define BOOST_PYTHON_YES_DATA_MEMBER , int
# define BOOST_PYTHON_NO_DATA_MEMBER , ...
# else
# define BOOST_PYTHON_DATA_MEMBER_HELPER
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
# define BOOST_PYTHON_YES_DATA_MEMBER
# define BOOST_PYTHON_NO_DATA_MEMBER
# endif
@@ -337,39 +344,39 @@ class class_ : public objects::class_base
template <class D>
self& def_readonly(char const* name, D const& d)
{
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D const& d)
{
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readonly(char const* name, D& d)
{
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D& d)
{
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
// Property creation
template <class Get>
self& add_property(char const* name, Get fget)
{
base::add_property(name, make_fn(fget));
base::add_property(name, this->make_getter(fget));
return *this;
}
template <class Get, class Set>
self& add_property(char const* name, Get fget, Set fset)
{
base::add_property(name, make_fn(fget), make_fn(fset));
base::add_property(name, this->make_getter(fget), this->make_setter(fset));
return *this;
}
@@ -408,6 +415,12 @@ class class_ : public objects::class_base
return *this;
}
self& enable_pickling()
{
this->base::enable_pickling_(false);
return *this;
}
self& staticmethod(char const* name)
{
this->make_method_static(name);
@@ -415,25 +428,55 @@ class class_ : public objects::class_base
}
private: // helper functions
// Builds a method for this class around the given [member]
// function pointer or object, appropriately adjusting the type of
// the first signature argument so that if f is a member of a
// (possibly not wrapped) base class of T, an lvalue argument of
// type T will be required.
//
// @group make_fn {
// @group PropertyHelpers {
template <class F>
object make_fn(F const& f)
object make_getter(F f)
{
return make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
);
}
template <class F>
object make_setter(F f)
{
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
);
}
template <class F>
object make_fn_impl(F const& f, mpl::false_, void*, mpl::false_)
{
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
}
object
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
const&
# endif
make_fn(object const& x)
template <class D, class B>
object make_fn_impl(D B::*pm_, mpl::false_, char*, mpl::true_)
{
D T::*pm = pm_;
return python::make_getter(pm);
}
template <class D, class B>
object make_fn_impl(D B::*pm_, mpl::false_, int*, mpl::true_)
{
D T::*pm = pm_;
return python::make_setter(pm);
}
template <class F>
object make_fn_impl(F const& x, mpl::true_, void*, mpl::false_)
{
return x;
}
@@ -443,30 +486,28 @@ class class_ : public objects::class_base
self& def_readonly_impl(
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
D T::*pm = pm_;
return this->add_property(name, make_getter(pm));
return this->add_property(name, pm_);
}
template <class D, class B>
self& def_readwrite_impl(
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
D T::*pm = pm_;
return this->add_property(name, make_getter(pm), make_setter(pm));
return this->add_property(name, pm_, pm_);
}
template <class D>
self& def_readonly_impl(
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, make_getter(d));
return this->add_static_property(name, python::make_getter(d));
}
template <class D>
self& def_readwrite_impl(
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, make_getter(d), make_setter(d));
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
}
inline void register_() const;

View File

@@ -8,6 +8,7 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/python/handle.hpp>
# include <boost/implicit_cast.hpp>
# include <string>
# include <complex>
# include <boost/limits.hpp>
@@ -111,9 +112,9 @@ 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 const*, converter::do_return_to_python(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),x.size()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<int>(x.size())))
# ifndef BOOST_NO_STD_WSTRING
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),x.size()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<int>(x.size())))
# endif
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))

View File

@@ -19,14 +19,13 @@ struct shared_ptr_from_python
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >());
}
static shared_ptr_from_python const registration;
private:
static void* convertible(PyObject* p)
{
return p == Py_None
? p
: converter::get_lvalue_from_python(p, registered<T>::converters)
;
if (p == Py_None)
return p;
return converter::get_lvalue_from_python(p, registered<T>::converters);
}
static void construct(PyObject* source, rvalue_from_python_stage1_data* data)
@@ -45,9 +44,6 @@ struct shared_ptr_from_python
}
};
template <class T>
shared_ptr_from_python<T> const shared_ptr_from_python<T>::registration;
}}} // namespace boost::python::converter
#endif // SHARED_PTR_FROM_PYTHON_DWA20021130_HPP

View File

@@ -9,6 +9,7 @@
# include <boost/python/refcount.hpp>
# include <boost/python/converter/shared_ptr_deleter.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/get_pointer.hpp>
namespace boost { namespace python { namespace converter {
@@ -18,7 +19,7 @@ PyObject* shared_ptr_to_python(shared_ptr<T> const& x)
if (!x)
return python::detail::none();
else if (shared_ptr_deleter* d = boost::get_deleter<shared_ptr_deleter>(x))
return incref(d->owner.get());
return incref( get_pointer( d->owner ) );
else
return converter::registered<shared_ptr<T> const&>::converters.to_python(&x);
}

View File

@@ -41,19 +41,11 @@
namespace boost { namespace python { namespace detail {
# if 0 // argpkg
template <class N>
inline PyObject* get(N, PyObject* const& args_)
{
return PyTuple_GET_ITEM(args_,N::value);
}
# else
template <unsigned N>
inline PyObject* get(PyObject* const& args_ BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(unsigned,N))
template <int N>
inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
{
return PyTuple_GET_ITEM(args_,N);
}
# endif
inline unsigned arity(PyObject* const& args_)
{
@@ -106,21 +98,12 @@ struct caller;
# define BOOST_PYTHON_NEXT(init,name,n) \
typedef BOOST_PP_IF(n,typename BOOST_PP_CAT(name,BOOST_PP_DEC(n)) ::next, init) name##n;
# if 0 // argpkg
# define BOOST_PYTHON_ARG_CONVERTER(n) \
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
c_t##n c##n(get(mpl::int_<n>(), inner_args)); \
if (!c##n.convertible()) \
return 0;
# else
# define BOOST_PYTHON_ARG_CONVERTER(n) \
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
c_t##n c##n(get<n>(inner_args)); \
if (!c##n.convertible()) \
return 0;
# endif
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))

View File

@@ -15,4 +15,4 @@ namespace boost { namespace python { namespace detail {
}
}
}}} // namespace boost::python::detail
# endif // BOOST_PYTHON_DETAIL_DEALLOC_HPP_
# endif // BOOST_PYTHON_DETAIL_DEALLOC_HPP_

View File

@@ -14,36 +14,39 @@
# include <boost/type_traits/is_reference.hpp>
# 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; \
\
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(test(dummy, 0)) == sizeof(yes))); \
\
typedef mpl::bool_<value> type; \
# 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_ \
struct is_##name : mpl::false_ \
{ \
}; \
\
@@ -51,7 +54,7 @@ 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_ \
: mpl::true_ \
{ \
};

View File

@@ -18,7 +18,7 @@
/* Enable compiler features; switching on C lib defines doesn't work
here, because the symbols haven't necessarily been defined yet. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# define _GNU_SOURCE 1
#endif
/* Forcing SUSv2 compatibility still produces problems on some
@@ -26,7 +26,7 @@
define is switched off. */
#if 0
#ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500
# define _XOPEN_SOURCE 500
#endif
#endif
@@ -40,10 +40,10 @@
#endif
/* pyconfig.h may or may not define DL_IMPORT */
#ifndef DL_IMPORT /* declarations for DLL import/export */
#ifndef DL_IMPORT /* declarations for DLL import/export */
#define DL_IMPORT(RTYPE) RTYPE
#endif
#ifndef DL_EXPORT /* declarations for DLL import/export */
#ifndef DL_EXPORT /* declarations for DLL import/export */
#define DL_EXPORT(RTYPE) RTYPE
#endif
@@ -124,15 +124,15 @@ extern "C" { // Boost.Python modification: provide missing extern "C"
#include "abstract.h"
#define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a))
#define PyArg_NoArgs(v) PyArg_Parse(v, "")
#define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a))
#define PyArg_NoArgs(v) PyArg_Parse(v, "")
/* Convert a possibly signed character to a nonnegative int */
/* XXX This assumes characters are 8 bits wide */
#ifdef __CHAR_UNSIGNED__
#define Py_CHARMASK(c) (c)
#define Py_CHARMASK(c) (c)
#else
#define Py_CHARMASK(c) ((c) & 0xff)
#define Py_CHARMASK(c) ((c) & 0xff)
#endif
#include "pyfpe.h"

View File

@@ -88,7 +88,10 @@ result(X const&, short = 0) { return 0; }
/* --------------- function pointers --------------- */
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers))
# endif
# define N BOOST_PP_ITERATION()
@@ -108,7 +111,10 @@ boost::type<R>* result(R (*pf)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)), int = 0)
# include BOOST_PP_ITERATE()
#elif BOOST_PP_ITERATION_DEPTH() == 2
# line BOOST_PP_LINE(__LINE__, result.hpp(pointers-to-members))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, result.hpp(pointers-to-members))
# endif
// Inner over arities
# define N BOOST_PP_ITERATION()

View File

@@ -39,7 +39,10 @@ T& (* target(R (T::*)) )() { return 0; }
/* --------------- function pointers --------------- */
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers))
# endif
# define N BOOST_PP_ITERATION()
@@ -59,7 +62,10 @@ BOOST_PP_IF(N, A0, void)(* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))) )()
# include BOOST_PP_ITERATE()
#elif BOOST_PP_ITERATION_DEPTH() == 2
# line BOOST_PP_LINE(__LINE__, target.hpp(pointers-to-members))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, target.hpp(pointers-to-members))
# endif
// Inner over arities
# define N BOOST_PP_ITERATION()

View File

@@ -137,6 +137,24 @@ class handle
T* m_p;
};
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace python
#endif
template<class T> inline T * get_pointer(python::handle<T> const & p)
{
return p.get();
}
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace python {
#else
// We don't want get_pointer above to hide the others
using boost::get_pointer;
#endif
typedef handle<PyTypeObject> type_handle;
//

View File

@@ -38,13 +38,13 @@ class long_ : public detail::long_base
template <class T>
explicit long_(T const& rhs)
: base(object(rhs))
: detail::long_base(object(rhs))
{
}
template <class T, class U>
explicit long_(T const& rhs, U const& base)
: base(object(rhs), object(base))
: detail::long_base(object(rhs), object(base))
{
}

View File

@@ -85,19 +85,11 @@ namespace detail
BaseArgs base;
};
# if 0
template <class N, class BaseArgs, class Offset>
inline PyObject* get(N, offset_args<BaseArgs,Offset> const& args_)
template <int N, class BaseArgs, class Offset>
inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
{
return get(mpl::int_<(N::value+Offset::value)>(), args_.base);
return get(mpl::int_<(N+Offset::value)>(), args_.base);
}
# else
template <unsigned N, class BaseArgs, class Offset>
inline PyObject* get(offset_args<BaseArgs,Offset> const& args_ BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(unsigned,N))
{
return get<(N + Offset::value)>(args_.base);
}
# endif
template <class BaseArgs, class Offset>
inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)

View File

@@ -32,7 +32,7 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
// Implementation detail. Hiding this in the private section would
// require use of template friend declarations.
void enable_pickling(bool getstate_manages_dict);
void enable_pickling_(bool getstate_manages_dict);
protected:
void add_property(char const* name, object const& fget);

View File

@@ -18,6 +18,8 @@
# include <boost/mpl/for_each.hpp>
# include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace objects {
//////////////////////////////////////////////////////////////////////
@@ -76,8 +78,9 @@ struct register_base_of
template <class Derived, class Bases>
inline void register_class_from_python(Derived* = 0, Bases* = 0)
{
python::detail::force_instantiate(converter::shared_ptr_from_python<Derived>::registration);
// Static object constructor performs registration
static converter::shared_ptr_from_python<Derived> shared_ptr_registration;
// register all up/downcasts here
register_dynamic_id<Derived>();

View File

@@ -45,7 +45,10 @@ template <int nargs> struct make_holder;
# endif // MAKE_HOLDER_DWA20011215_HPP
#elif BOOST_PP_ITERATION_DEPTH() == 1
# line BOOST_PP_LINE(__LINE__, make_holder.hpp)
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, make_holder.hpp)
# endif
# define N BOOST_PP_ITERATION()

View File

@@ -26,8 +26,8 @@ struct make_instance_impl
PyTypeObject* type = Derived::get_class_object(x);
if (type == 0)
return python::detail::none();
if (type == 0)
return python::detail::none();
PyObject* raw_result = type->tp_alloc(
type, objects::additional_instance_size<Holder>::value);

View File

@@ -10,6 +10,7 @@
# include <boost/python/converter/registry.hpp>
# include <boost/type_traits/is_polymorphic.hpp>
# include <boost/get_pointer.hpp>
# include <boost/detail/workaround.hpp>
# include <typeinfo>
namespace boost { namespace python { namespace objects {
@@ -34,8 +35,8 @@ struct make_ptr_instance
template <class U>
static inline PyTypeObject* get_class_object_impl(U const volatile* p)
{
if (p == 0)
return 0; // means "return None".
if (p == 0)
return 0; // means "return None".
PyTypeObject* derived = get_derived_class_object(
BOOST_DEDUCED_TYPENAME is_polymorphic<U>::type(), p);
@@ -48,19 +49,15 @@ struct make_ptr_instance
template <class U>
static inline PyTypeObject* get_derived_class_object(mpl::true_, U const volatile* x)
{
converter::registration const* r = converter::registry::query(type_info(typeid(*x)));
converter::registration const* r = converter::registry::query(
type_info(typeid(*get_pointer(x)))
);
return r ? r->m_class_object : 0;
}
template <class U>
static inline PyTypeObject* get_derived_class_object(mpl::false_, U* x)
static inline PyTypeObject* get_derived_class_object(mpl::false_, U*)
{
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
if (typeid(*x) != typeid(U))
return get_derived_class_object(mpl::true_(), x);
# else
(void)x;
# endif
return 0;
}
};

View File

@@ -59,7 +59,7 @@ namespace detail {
inaccessible* (*setstate_fn)(),
bool)
{
cl.enable_pickling(false);
cl.enable_pickling_(false);
cl.def("__getinitargs__", getinitargs_fn);
}
@@ -75,7 +75,7 @@ namespace detail {
void (*setstate_fn)(Tsetstate, Ttuple),
bool getstate_manages_dict)
{
cl.enable_pickling(getstate_manages_dict);
cl.enable_pickling_(getstate_manages_dict);
cl.def("__getstate__", getstate_fn);
cl.def("__setstate__", setstate_fn);
}
@@ -93,7 +93,7 @@ namespace detail {
void (*setstate_fn)(Tsetstate, Ttuple),
bool getstate_manages_dict)
{
cl.enable_pickling(getstate_manages_dict);
cl.enable_pickling_(getstate_manages_dict);
cl.def("__getinitargs__", getinitargs_fn);
cl.def("__getstate__", getstate_fn);
cl.def("__setstate__", setstate_fn);

View File

@@ -9,6 +9,7 @@
# ifndef POINTER_HOLDER_DWA20011215_HPP
# define POINTER_HOLDER_DWA20011215_HPP
# include <boost/get_pointer.hpp>
# include <boost/type.hpp>
# include <boost/python/instance_holder.hpp>
@@ -29,20 +30,10 @@
# include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
# include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace objects {
template <class T>
bool is_null(T const& p, ...)
{
return p.get() == 0;
}
template <class T>
bool is_null(T* p, int)
{
return p == 0;
}
# if BOOST_WORKAROUND(__GNUC__, == 2)
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0)
# else
@@ -113,11 +104,11 @@ void* pointer_holder<Pointer, Value>::holds(type_info dst_t)
if (dst_t == python::type_id<Pointer>())
return &this->m_p;
if (objects::is_null(this->m_p, 0))
Value* p = get_pointer(this->m_p);
if (p == 0)
return 0;
type_info src_t = python::type_id<Value>();
Value* p = &*this->m_p;
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
}
@@ -127,14 +118,15 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
if (dst_t == python::type_id<Pointer>())
return &this->m_p;
if (objects::is_null(this->m_p, 0))
if (!get_pointer(this->m_p))
return 0;
Value* p = get_pointer(m_p);
if (dst_t == python::type_id<held_type>())
return &*this->m_p;
return p;
type_info src_t = python::type_id<Value>();
Value* p = &*this->m_p;
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
}
@@ -144,7 +136,10 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
/* --------------- pointer_holder --------------- */
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
# endif
# define N BOOST_PP_ITERATION()
@@ -161,7 +156,10 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
/* --------------- pointer_holder_back_reference --------------- */
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp(pointer_holder_back_reference))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp(pointer_holder_back_reference))
# endif
# define N BOOST_PP_ITERATION()

View File

@@ -103,7 +103,10 @@ void* value_holder_back_reference<Value,Held>::holds(
// --------------- value_holder ---------------
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder))
# endif
# define N BOOST_PP_ITERATION()
@@ -122,7 +125,10 @@ void* value_holder_back_reference<Value,Held>::holds(
// --------------- value_holder_back_reference ---------------
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder_back_reference))
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder_back_reference))
# endif
# define N BOOST_PP_ITERATION()

View File

@@ -13,7 +13,6 @@
# include <boost/python/call.hpp>
# include <boost/python/handle_fwd.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/refcount.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/tag.hpp>
@@ -63,6 +62,7 @@ namespace api
struct item_policies;
struct const_slice_policies;
struct slice_policies;
class slice_nil;
typedef proxy<const_attribute_policies> const_object_attribute;
typedef proxy<attribute_policies> object_attribute;
@@ -146,6 +146,9 @@ namespace api
const_object_slice slice(object_cref, slice_nil) const;
object_slice slice(object_cref, slice_nil);
const_object_slice slice(slice_nil, slice_nil) const;
object_slice slice(slice_nil, slice_nil);
template <class T, class V>
const_object_slice
slice(T const& start, V const& end) const
@@ -468,4 +471,6 @@ inline PyObject* get_managed_object(object const& x, tag_t)
}} // namespace boost::python
# include <boost/python/slice_nil.hpp>
#endif // OBJECT_CORE_DWA2002615_HPP

View File

@@ -17,8 +17,6 @@
namespace boost { namespace python { namespace api {
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
template <class X>
char is_object_operators_helper(object_operators<X> const*);
@@ -27,7 +25,7 @@ no_type is_object_operators_helper(...);
template <class X> X* make_ptr();
template <class L, class R>
template <class L, class R = L>
struct is_object_operators
{
enum {
@@ -40,6 +38,7 @@ struct is_object_operators
typedef mpl::bool_<value> type;
};
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
template <class L, class R, class T>
struct enable_binary
: boost::iterators::enable_if<is_object_operators<L,R>, T>

View File

@@ -63,6 +63,22 @@ object_operators<U>::slice(slice_nil, object_cref finish) const
return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr())));
}
template <class U>
object_slice
object_operators<U>::slice(slice_nil, slice_nil)
{
object_cref2 x = *static_cast<U*>(this);
return object_slice(x, std::make_pair(allow_null((PyObject*)0), allow_null((PyObject*)0)));
}
template <class U>
const_object_slice
object_operators<U>::slice(slice_nil, slice_nil) const
{
object_cref2 x = *static_cast<U const*>(this);
return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), allow_null((PyObject*)0)));
}
template <class U>
object_slice
object_operators<U>::slice(object_cref start, slice_nil)

View File

@@ -133,4 +133,4 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
} \
}}
# endif
# endif // OPAQUE_POINTER_CONVERTER_HPP_
# endif // OPAQUE_POINTER_CONVERTER_HPP_

View File

@@ -11,9 +11,7 @@
# include <boost/type_traits/add_reference.hpp>
# include <boost/type_traits/add_const.hpp>
# if 0 // argpkg
# include <boost/mpl/int.hpp>
# endif
# include <boost/mpl/int.hpp>
# include <boost/static_assert.hpp>
# include <boost/python/refcount.hpp>
@@ -86,11 +84,7 @@ struct return_arg : Base
if (!result)
return 0;
Py_DECREF(result);
# if 0 // argpkg
return incref( detail::get(mpl::int_<arg_pos-1>(),args) );
# else
return incref( detail::get<(arg_pos-1)>(args) );
# endif
}
};

View File

@@ -0,0 +1,252 @@
#ifndef BOOST_PYTHON_SLICE_JDB20040105_HPP
#define BOOST_PYTHON_SLICE_JDB20040105_HPP
// Copyright (c) 2004 Jonathan Brandmeyer
// Use, modification and distribution are subject to 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/extract.hpp>
#include <boost/python/converter/pytype_object_mgr_traits.hpp>
#include <iterator>
#include <algorithm>
namespace boost { namespace python {
class slice : public object
{
public:
// Equivalent to slice(::)
slice();
// Each argument must be int, slice_nil, or implicitly convertable to int
template<typename Integer1, typename Integer2>
slice( Integer1 start, Integer2 stop)
: object( boost::python::detail::new_reference(
PySlice_New( object(start).ptr(), object(stop).ptr(), NULL)))
{}
template<typename Integer1, typename Integer2, typename Integer3>
slice( Integer1 start, Integer2 stop, Integer3 stride)
: object( boost::python::detail::new_reference(
PySlice_New( object(start).ptr(), object(stop).ptr(),
object(stride).ptr())))
{}
// Get the Python objects associated with the slice. In principle, these
// may be any arbitrary Python type, but in practice they are usually
// integers. If one or more parameter is ommited in the Python expression
// that created this slice, than that parameter is None here, and compares
// equal to a default-constructed boost::python::object.
// If a user-defined type wishes to support slicing, then support for the
// special meaning associated with negative indicies is up to the user.
object start();
object stop();
object step();
// The following algorithm is intended to automate the process of
// determining a slice range when you want to fully support negative
// indicies and non-singular step sizes. Its functionallity is simmilar to
// PySlice_GetIndicesEx() in the Python/C API, but tailored for C++ users.
// This template returns a slice::range struct that, when used in the
// following iterative loop, will traverse a slice of the function's
// arguments.
// while (start != end) {
// do_foo(...);
// std::advance( start, step);
// }
// do_foo(...); // repeat exactly once more.
// Arguments: a [begin, end) pair of STL-conforming random-access iterators.
// Return: slice::range, where start and stop define a _closed_ interval
// that covers at most [begin, end-1] of the provided arguments, and a step
// that is non-zero.
// Throws: error_already_set() if any of the indices are neither None nor
// integers, or the slice has a step value of zero.
// std::invalid_argument if the resulting range would be empty. Normally,
// you should catch this exception and return an empty sequence of the
// appropriate type.
// Performance: constant time for random-access iterators.
// Rationale:
// closed-interval: If an open interval were used, then for a non-singular
// value for step, the required state for the end iterator could be
// beyond the one-past-the-end postion of the specified range. While
// probably harmless, the behavior of STL-conforming iterators is
// undefined in this case.
// exceptions on zero-length range: It is impossible to define a closed
// interval over an empty range, so some other form of error checking
// would have to be used by the user to prevent undefined behavior. In
// the case where the user fails to catch the exception, it will simply
// be translated to Python by the default exception handling mechanisms.
#ifndef BOOST_NO_MEMBER_TEMPLATES
template<typename RandomAccessIterator>
struct range
{
RandomAccessIterator start;
RandomAccessIterator stop;
int step;
};
template<typename RandomAccessIterator>
range<RandomAccessIterator>
get_indicies( const RandomAccessIterator& begin,
const RandomAccessIterator& end)
{
// This is based loosely on PySlice_GetIndicesEx(), but it has been
// carefully crafted to ensure that these iterators never fall out of
// the range of the container.
slice::range<RandomAccessIterator> ret;
typename RandomAccessIterator::difference_type max_dist =
std::distance( begin, end);
object slice_start = this->start();
object slice_stop = this->stop();
object slice_step = this->step();
// Extract the step.
if (slice_step == object()) {
ret.step = 1;
}
else {
ret.step = extract<int>( slice_step);
if (ret.step == 0) {
PyErr_SetString( PyExc_IndexError, "step size cannot be zero.");
throw_error_already_set();
}
}
// Setup the start iterator.
if (slice_start == object()) {
if (ret.step < 0) {
ret.start = end;
--ret.start;
}
else
ret.start = begin;
}
else {
int i = extract<int>( slice_start);
if (i >= max_dist && ret.step > 0)
throw std::invalid_argument( "Zero-length slice");
if (i >= 0) {
ret.start = begin;
std::advance( ret.start, std::min(i, max_dist-1));
}
else {
if (i < -max_dist && ret.step < 0)
throw std::invalid_argument( "Zero-length slice");
ret.start = end;
// Advance start (towards begin) not farther than begin.
std::advance( ret.start, (-i < max_dist) ? i : -max_dist );
}
}
// Set up the stop iterator. This one is a little trickier since slices
// define a [) range, and we are returning a [] range.
if (slice_stop == object()) {
if (ret.step < 0) {
ret.stop = begin;
}
else {
ret.stop = end;
std::advance( ret.stop, -1);
}
}
else {
int i = extract<int>( slice_stop);
// First, branch on which direction we are going with this.
if (ret.step < 0) {
if (i+1 >= max_dist || i == -1)
throw std::invalid_argument( "Zero-length slice");
if (i >= 0) {
ret.stop = begin;
std::advance( ret.stop, i+1);
}
else { // i is negative, but more negative than -1.
ret.stop = end;
std::advance( ret.stop, (-i < max_dist) ? i : -max_dist);
}
}
else { // stepping forward
if (i == 0 || -i >= max_dist)
throw std::invalid_argument( "Zero-length slice");
if (i > 0) {
ret.stop = begin;
std::advance( ret.stop, std::min( i-1, max_dist-1));
}
else { // i is negative, but not more negative than -max_dist
ret.stop = end;
std::advance( ret.stop, i-1);
}
}
}
// Now the fun part, handling the possibilites surrounding step.
// At this point, step has been initialized, ret.stop, and ret.step
// represent the widest possible range that could be traveled
// (inclusive), and final_dist is the maximum distance covered by the
// slice.
typename RandomAccessIterator::difference_type final_dist =
std::distance( ret.start, ret.stop);
// First case, if both ret.start and ret.stop are equal, then step
// is irrelevant and we can return here.
if (final_dist == 0)
return ret;
// Second, if there is a sign mismatch, than the resulting range and
// step size conflict: std::advance( ret.start, ret.step) goes away from
// ret.stop.
if ((final_dist > 0) != (ret.step > 0))
throw std::invalid_argument( "Zero-length slice.");
// Finally, if the last step puts us past the end, we move ret.stop
// towards ret.start in the amount of the remainder.
// I don't remember all of the oolies surrounding negative modulii,
// so I am handling each of these cases separately.
if (final_dist < 0) {
int remainder = -final_dist % -ret.step;
std::advance( ret.stop, remainder);
}
else {
int remainder = final_dist % ret.step;
std::advance( ret.stop, -remainder);
}
return ret;
}
#endif // !defined BOOST_NO_MEMBER_TEMPLATES
public:
// This declaration, in conjunction with the specialization of
// object_manager_traits<> below, allows C++ functions accepting slice
// arguments to be called from from Python. These constructors should never
// be used in client code.
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice, object)
};
namespace converter {
template<>
struct object_manager_traits<slice>
: pytype_object_manager_traits<&PySlice_Type, slice>
{
};
} // !namesapce converter
} } // !namespace ::boost::python
#endif // !defined BOOST_PYTHON_SLICE_JDB20040105_HPP

View File

@@ -7,18 +7,20 @@
# define SLICE_NIL_DWA2002620_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/object_core.hpp>
namespace boost { namespace python { namespace api {
class object;
enum slice_nil
class slice_nil : public object
{
# ifndef _ // Watch out for GNU gettext users, who #define _(x)
_
# endif
public:
slice_nil() : object() {}
};
# ifndef _ // Watch out for GNU gettext users, who #define _(x)
static const slice_nil _ = slice_nil();
# endif
template <class T>
struct slice_bound
{

View File

@@ -9,8 +9,8 @@
# include <boost/python/extract.hpp>
# include <boost/scoped_ptr.hpp>
# include <boost/detail/binary_search.hpp>
# include <boost/get_pointer.hpp>
# include <boost/detail/binary_search.hpp>
# include <vector>
# include <map>
@@ -366,9 +366,9 @@ namespace boost { namespace python { namespace detail {
}
container_element(container_element const& ce)
: ptr(ce.ptr.get() == 0 ? 0 : new element_type(*ce.ptr.get()))
, container(ce.container)
, index(ce.index)
: ptr(ce.ptr.get() == 0 ? 0 : new element_type(*ce.ptr.get()))
, container(ce.container)
, index(ce.index)
{
}
@@ -381,14 +381,14 @@ namespace boost { namespace python { namespace detail {
element_type& operator*() const
{
if (is_detached())
return *ptr.get();
return *get_pointer(ptr);
return Policies::get_item(get_container(), index);
}
element_type* get() const
{
if (is_detached())
return ptr.get();
return get_pointer(ptr);
return &Policies::get_item(get_container(), index);
}
@@ -407,7 +407,7 @@ namespace boost { namespace python { namespace detail {
bool
is_detached() const
{
return ptr.get() != 0;
return get_pointer(ptr) != 0;
}
Container&
@@ -690,7 +690,9 @@ namespace boost { namespace python { namespace detail {
}
};
}} // namespace python::detail
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
}} // namespace python::detail
#endif
template <class Container, class Index, class Policies>
inline typename Policies::data_type*
@@ -701,6 +703,13 @@ namespace boost { namespace python { namespace detail {
return p.get();
}
#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
// Don't hide these other get_pointer overloads
using boost::python::get_pointer;
using boost::get_pointer;
}} // namespace python::detail
#endif
} // namespace boost
#endif // INDEXING_SUITE_DETAIL_JDG20036_HPP

View File

@@ -182,13 +182,7 @@ namespace boost { namespace python {
.def("__delitem__", &base_delete_item)
.def("__getitem__", &base_get_item)
.def("__contains__", &base_contains)
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
// crazy VC6 doesn't like this! perhaps there's a better
// fix but this one will do for now. def __iter__ is just
// an optimization anyway.
.def("__iter__", def_iterator())
#endif
;
DerivedPolicies::extension_def(cl);

View File

@@ -17,8 +17,9 @@
# include <boost/type_traits/same_traits.hpp>
# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__GNUC__) \
&& ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
# if defined(__GNUC__) \
&& ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) \
&& !defined(__EDG_VERSION__)
# define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# endif
# endif
@@ -78,7 +79,8 @@ inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T))
);
}
# if defined(__EDG_VERSION__) && __EDG_VERSION__ < 245
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 741)
// Older EDG-based compilers seems to mistakenly distinguish "int" from
// "signed int", etc., but only in typeid() expressions. However
// though int == signed int, the "signed" decoration is propagated

View File

@@ -16,13 +16,14 @@ namespace boost { namespace python {
namespace detail
{
template <unsigned N>
template <std::size_t N>
struct get_prev
{
template <class ArgumentPackage>
static PyObject* execute(ArgumentPackage const& args, PyObject*)
static PyObject* execute(ArgumentPackage const& args, PyObject* = 0)
{
return get<(N-1)>(args);
int const pre_n = static_cast<int>(N) - 1; // separate line is gcc-2.96 workaround
return detail::get(mpl::int_<pre_n>(), args);
}
};
template <>
@@ -59,13 +60,9 @@ struct with_custodian_and_ward : BasePolicy_
return false;
}
# if 0 // argpkg
PyObject* patient = detail::get(mpl::int_<(ward-1)>(), args_);
PyObject* nurse = detail::get(mpl::int_<(custodian-1)>(), args_);
# else
PyObject* patient = detail::get<(ward-1)>(args_);
PyObject* nurse = detail::get<(custodian-1)>(args_);
# endif
PyObject* patient = detail::get_prev<ward>::execute(args_);
PyObject* nurse = detail::get_prev<custodian>::execute(args_);
PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
if (life_support == 0)
return false;
@@ -97,13 +94,9 @@ struct with_custodian_and_ward_postcall : BasePolicy_
return 0;
}
# if 0 // argpkg
PyObject* patient = ward > 0 ? detail::get(mpl::int_<(ward-1)>(),args_) : result;
PyObject* nurse = custodian > 0 ? detail::get(mpl::int_<(custodian-1)>(),args_) : result;
# else
PyObject* patient = detail::get_prev<ward>::execute(args_, result);
PyObject* nurse = detail::get_prev<custodian>::execute(args_, result);
# endif
if (nurse == 0) return 0;
result = BasePolicy_::postcall(args_, result);

View File

@@ -253,12 +253,13 @@ class ClassExporter(Exporter):
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
self.constructors = constructors[:]
# don't export the copy constructor if the class is abstract
# don't export constructors if the class is abstract
if self.class_.abstract:
for cons in constructors:
if cons.IsCopy():
constructors.remove(cons)
break
if not constructors:
# declare no_init
self.Add('constructor', py_ns + 'no_init')

View File

@@ -24,8 +24,6 @@ class EnumExporter(Exporter):
else:
self.enum = None
TYPE_COUNT = 0
def Export(self, codeunit, exported_names):
if not self.info.exclude:
indent = self.INDENT
@@ -34,10 +32,10 @@ class EnumExporter(Exporter):
full_name = self.enum.FullName()
unnamed_enum = False
if rename.startswith('$_') or rename.startswith('._'):
unique_number = hash(self.info.include)
unnamed_enum = True
self.ExportUniqueInt(codeunit)
full_name = namespaces.pyste + 'UniqueInt<%d>' % EnumExporter.TYPE_COUNT
EnumExporter.TYPE_COUNT += 1
full_name = namespaces.pyste + 'UniqueInt<%d>' % unique_number
rename = "unnamed"
code = indent + namespaces.python
code += 'enum_< %s >("%s")\n' % (full_name, rename)

View File

@@ -14,7 +14,7 @@ from VarExporter import VarExporter
from CodeExporter import CodeExporter
from exporterutils import FunctionWrapper
from utils import makeid
import warnings
#==============================================================================
# DeclarationInfo
@@ -149,6 +149,7 @@ class EnumInfo(DeclarationInfo):
class HeaderInfo(DeclarationInfo):
def __init__(self, include, exporter_class = HeaderExporter):
warnings.warn('AllFromHeader is not working in all cases in the current version.')
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = exporter_class(InfoWrapper(self))

View File

@@ -51,7 +51,7 @@ from CppParser import CppParser, CppParserError
import time
import declarations
__version__ = '0.9.28'
__version__ = '0.9.29'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'

View File

@@ -12,7 +12,7 @@
#include <boost/lexical_cast.hpp>
#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \
&& __GNUC__ == 3 && __GNUC_MINOR__ == 3 && !defined(__APPLE_CC__)
&& __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__)
# define BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
#endif
@@ -134,7 +134,7 @@ namespace // <unnamed>
# ifdef BOOST_PYTHON_TRACE_REGISTRY
registry_t::iterator p = entries().find(entry(type));
std::cout << "looking up " << type
std::cout << "looking up " << type << ": "
<< (p == entries().end() || p->target_type != type
? "...NOT found\n" : "...found\n");
# endif

View File

@@ -13,7 +13,7 @@
#include <cstdlib>
#include <cstring>
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT || __EDG_VERSION__
# include <ostream>
#else
# include <ostream.h>
@@ -33,10 +33,19 @@ namespace boost { namespace python {
# if __GNUC__ < 3
namespace cxxabi = :: ;
# else
extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
# else
namespace cxxabi = ::abi; // GCC 3.1 and later
# if __GNUC__ == 3 && __GNUC_MINOR__ == 0
namespace abi
{
extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
}
# endif
# endif
# endif
# endif
namespace
{

View File

@@ -33,11 +33,8 @@ BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)())
if (m != 0)
{
// Create the current module scope
scope current_module(
(object(
((borrowed_reference_t*)m)
))
);
object m_obj(((borrowed_reference_t*)m));
scope current_module(m_obj);
handle_exception(init_function);
}

View File

@@ -317,7 +317,7 @@ namespace objects
// like, so we'll store the total size of the object
// there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders.
result->ob_size = -(offsetof(instance<>,storage) + instance_size);
result->ob_size = -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
}
return (PyObject*)result;
}
@@ -599,7 +599,7 @@ namespace objects
this->setattr("__init__", object(f));
}
void class_base::enable_pickling(bool getstate_manages_dict)
void class_base::enable_pickling_(bool getstate_manages_dict)
{
setattr("__reduce__", object(make_instance_reduce_function()));
setattr("__safe_for_unpickling__", object(true));

View File

@@ -16,6 +16,7 @@
#include <boost/python/tuple.hpp>
#include <boost/python/list.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/detail/signature.hpp>
#include <boost/mpl/vector/vector10.hpp>
@@ -233,13 +234,13 @@ void function::argument_error(PyObject* args, PyObject* keywords) const
object message = "Python argument types in\n %s.%s("
% make_tuple(this->m_namespace, this->m_name);
list actual;
list actual_args;
for (int i = 0; i < PyTuple_Size(args); ++i)
{
char const* name = PyTuple_GetItem(args, i)->ob_type->tp_name;
actual.append(str(name));
actual_args.append(str(name));
}
message += str(", ").join(actual);
message += str(", ").join(actual_args);
message += ")\ndid not match C++ signature:\n ";
list signatures;
@@ -248,27 +249,39 @@ void function::argument_error(PyObject* args, PyObject* keywords) const
py_function const& impl = f->m_fn;
python::detail::signature_element const* s
= impl.signature();
= impl.signature() + 1; // skip over return type
list formal;
list formal_params;
if (impl.max_arity() == 0)
formal.append("void");
formal_params.append("void");
for (unsigned n = 1; n <= impl.max_arity(); ++n)
for (unsigned n = 0; n < impl.max_arity(); ++n)
{
if (s[n].basename == 0)
{
formal.append("...");
formal_params.append("...");
break;
}
str param(s[n].basename);
if (s[n].lvalue)
param += " {lvalue}";
formal.append(
str(s[n].basename) + (s[n].lvalue ? " {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))
"%s(%s)" % make_tuple(f->m_name, str(", ").join(formal_params))
);
}

View File

@@ -35,6 +35,7 @@ namespace boost {
namespace
{
enum edge_cast_t { edge_cast = 8010 };
template <class T> inline void unused_variable(const T&) { }
}
// Install properties
@@ -126,8 +127,6 @@ namespace
cast_graph& topology() { return m_topology; }
cast_graph const& topology() const { return m_topology; }
std::size_t known_vertices() const { return m_known_vertices; }
smart_graph()
: m_known_vertices(0)
{}
@@ -215,7 +214,7 @@ namespace
vertex_t v = add_vertex(full_graph().topology());
vertex_t v2 = add_vertex(up_graph().topology());
(void)v2; // prevent unused var warning on non-debug compile
unused_variable(v2);
assert(v == v2);
return type_index().insert(p, boost::make_tuple(type, v, dynamic_id_function(0)));
}

View File

@@ -32,7 +32,7 @@ extern "C"
((life_support*)self)->patient = 0;
// Let the weak reference die. This probably kills us.
Py_XDECREF(PyTuple_GET_ITEM(arg, 0));
return detail::none();
return ::boost::python::detail::none();
}
}

38
src/slice.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "boost/python/slice.hpp"
// Copyright (c) 2004 Jonathan Brandmeyer
// Use, modification and distribution are subject to 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)
namespace boost { namespace python {
slice::slice()
: object( boost::python::detail::new_reference(
PySlice_New( NULL, NULL, NULL)))
{
}
object
slice::start()
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->start));
}
object
slice::stop()
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->stop));
}
object
slice::step()
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->step));
}
} } // !namespace boost::python

View File

@@ -5,8 +5,29 @@
subproject libs/python/test ;
# bring in the rules for python and testing
import python testing ;
import python ;
if [ check-python-config ]
{
# 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) ;
}
template py-unit-test
:
: $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
[ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ] <define>BOOST_PYTHON_STATIC_LIB
;
# Convenience rule makes declaring tests faster
rule bpl-test ( name ? : files * : requirements * )
{
@@ -43,159 +64,136 @@ rule bpl-test ( name ? : files * : requirements * )
m = $(m)_ext ;
}
}
extension $(m) : $(f) <dll>../build/boost_python : $(requirements) ;
extension $(m) : $(f) <template>../build/extension : $(requirements) ;
modules += $(m) ;
}
}
boost-python-runtest $(name) : $(py) <pyd>$(modules) ;
return [ boost-python-runtest $(name) : $(py) <pyd>$(modules) : $(requirements) ] ;
}
run ../test/embedding.cpp <lib>../build/boost_python
: # program args
: # input files
: # requirements
$(PYTHON_PROPERTIES)
<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_STATIC_MODULE
<library-path>$(PYTHON_LIB_PATH)
<$(gcc-compilers)><debug-python><library-path>$(CYGWIN_PYTHON_DEBUG_DLL_PATH)
<$(gcc-compilers)><*><library-path>$(CYGWIN_PYTHON_DLL_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
test-suite python
:
[
run ../test/embedding.cpp <lib>../build/boost_python
: # program args
: # input files
: # requirements
$(PYTHON_PROPERTIES)
<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_STATIC_MODULE
<library-path>$(PYTHON_LIB_PATH)
<$(gcc-compilers)><debug-python><library-path>$(CYGWIN_PYTHON_DEBUG_DLL_PATH)
<$(gcc-compilers)><*><library-path>$(CYGWIN_PYTHON_DLL_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY)
]
[
bpl-test crossmod_exception
: crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp
;
]
bpl-test injected ;
bpl-test properties ;
bpl-test return_arg ;
bpl-test staticmethod ;
bpl-test shared_ptr ;
bpl-test polymorphism ;
bpl-test auto_ptr ;
bpl-test minimal ;
bpl-test args ;
bpl-test numpy ;
bpl-test enum ;
bpl-test exception_translator ;
bpl-test pearu1 : test_cltree.py cltree.cpp ;
bpl-test try : newtest.py m1.cpp m2.cpp ;
[ bpl-test injected ]
[ bpl-test properties ]
[ bpl-test return_arg ]
[ bpl-test staticmethod ]
[ bpl-test shared_ptr ]
[ bpl-test polymorphism ]
[ bpl-test auto_ptr ]
[ bpl-test minimal ]
[ bpl-test args ]
[ bpl-test numpy ]
[ bpl-test enum ]
[ bpl-test exception_translator ]
[ bpl-test pearu1 : test_cltree.py cltree.cpp ]
[ bpl-test try : newtest.py m1.cpp m2.cpp ]
bpl-test keywords : keywords.cpp keywords_test.py ;
[ bpl-test keywords : keywords.cpp keywords_test.py ]
extension builtin_converters : test_builtin_converters.cpp <dll>../build/boost_python ;
boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ;
[ extension builtin_converters : test_builtin_converters.cpp <template>../build/extension ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ]
bpl-test test_pointer_adoption ;
bpl-test operators ;
bpl-test callbacks ;
bpl-test defaults ;
[ bpl-test test_pointer_adoption ]
[ bpl-test operators ]
[ bpl-test callbacks ]
[ bpl-test defaults ]
bpl-test object ;
bpl-test list ;
bpl-test long ;
bpl-test dict ;
bpl-test tuple ;
bpl-test str ;
[ bpl-test object ]
[ bpl-test list ]
[ bpl-test long ]
[ bpl-test dict ]
[ bpl-test tuple ]
[ bpl-test str ]
[ bpl-test slice ]
bpl-test virtual_functions ;
bpl-test back_reference ;
bpl-test implicit ;
bpl-test data_members ;
[ bpl-test virtual_functions ]
[ bpl-test back_reference ]
[ bpl-test implicit ]
[ bpl-test data_members ]
bpl-test ben_scott1 ;
[ bpl-test ben_scott1 ]
bpl-test bienstman1 ;
bpl-test bienstman2 ;
bpl-test bienstman3 ;
[ bpl-test bienstman1 ]
[ bpl-test bienstman2 ]
[ bpl-test bienstman3 ]
# 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) ;
}
bpl-test multi_arg_constructor
[ bpl-test multi_arg_constructor
: # files
: # requirements
turn-off-intel-debug-symbols ; # debug symbols slow the build down too much
turn-off-intel-debug-symbols ] # debug symbols slow the build down too much
bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ;
[ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ]
bpl-test extract ;
[ bpl-test extract ]
bpl-test opaque ;
[ bpl-test opaque ]
bpl-test pickle1 ;
bpl-test pickle2 ;
bpl-test pickle3 ;
[ bpl-test pickle1 ]
[ bpl-test pickle2 ]
[ bpl-test pickle3 ]
[ bpl-test pickle4 ]
bpl-test nested ;
[ bpl-test nested ]
bpl-test docstring ;
[ bpl-test docstring ]
bpl-test vector_indexing_suite ;
bpl-test map_indexing_suite ;
[ bpl-test vector_indexing_suite ]
[ bpl-test map_indexing_suite ]
if $(TEST_BIENSTMAN_NON_BUGS)
{
bpl-test bienstman4 ;
bpl-test bienstman5 ;
}
# if $(TEST_BIENSTMAN_NON_BUGS)
# {
# bpl-test bienstman4 ;
# bpl-test bienstman5 ;
# }
# --- unit tests of library components ---
local UNIT_TEST_PROPERTIES = $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
[ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ] <define>BOOST_PYTHON_STATIC_LIB ;
[ run indirect_traits_test.cpp ]
[ run destroy_test.cpp ]
[ run pointer_type_id_test.cpp <lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ run bases.cpp <template>py-unit-test ]
[ run if_else.cpp ]
[ run pointee.cpp <template>py-unit-test ]
[ run result.cpp ]
run indirect_traits_test.cpp ;
run destroy_test.cpp ;
run pointer_type_id_test.cpp <lib>../../test/build/boost_test_exec_monitor : : : $(UNIT_TEST_PROPERTIES) ;
run bases.cpp : : : $(UNIT_TEST_PROPERTIES) ;
run if_else.cpp ;
run pointee.cpp : : : $(UNIT_TEST_PROPERTIES) ;
run result.cpp ;
[ compile string_literal.cpp ]
[ compile borrowed.cpp <template>py-unit-test ]
[ compile object_manager.cpp <template>py-unit-test ]
[ compile copy_ctor_mutates_rhs.cpp <template>py-unit-test ]
compile string_literal.cpp ;
compile borrowed.cpp : $(UNIT_TEST_PROPERTIES) ;
compile object_manager.cpp : $(UNIT_TEST_PROPERTIES) ;
compile copy_ctor_mutates_rhs.cpp : $(UNIT_TEST_PROPERTIES) ;
run upcast.cpp <lib>../../test/build/boost_test_exec_monitor
: # command-line args
: # input files
: $(UNIT_TEST_PROPERTIES)
;
run select_holder.cpp <lib>../../test/build/boost_test_exec_monitor
: # command-line args
: # input files
: $(UNIT_TEST_PROPERTIES)
;
run select_from_python_test.cpp ../src/converter/type_id.cpp <lib>../../test/build/boost_test_exec_monitor
: # command-line args
: # input files
: $(UNIT_TEST_PROPERTIES)
;
run select_arg_to_python_test.cpp ../src/converter/type_id.cpp <lib>../../test/build/boost_test_exec_monitor
: # command-line args
: # input files
: $(UNIT_TEST_PROPERTIES)
;
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./as_to_python_function.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;
[ run upcast.cpp <lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ run select_holder.cpp <lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ run select_from_python_test.cpp ../src/converter/type_id.cpp
<lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ run select_arg_to_python_test.cpp ../src/converter/type_id.cpp
<lib>../../test/build/boost_test_exec_monitor <template>py-unit-test ]
[ compile-fail ./raw_pyobject_fail1.cpp <template>py-unit-test ]
[ compile-fail ./raw_pyobject_fail2.cpp <template>py-unit-test ]
[ compile-fail ./as_to_python_function.cpp <template>py-unit-test ]
[ compile-fail ./object_fail1.cpp <template>py-unit-test ]
;
}

View File

@@ -4,6 +4,7 @@
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/module.hpp>
#include "test_class.hpp"
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/tuple.hpp>
@@ -11,7 +12,6 @@
#include <boost/python/overloads.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/return_internal_reference.hpp>
#include "test_class.hpp"
using namespace boost::python;

View File

@@ -5,6 +5,7 @@
// to its suitability for any purpose.
#include <boost/python/module.hpp>
#include "test_class.hpp"
#include <boost/python/class.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/def.hpp>
@@ -12,7 +13,6 @@
#include <boost/detail/workaround.hpp>
#include "test_class.hpp"
#include <memory>
using namespace boost::python;

View File

@@ -153,7 +153,7 @@ BOOST_PYTHON_MODULE(defaults_ext)
def("bar", (object(*)(int, char, std::string, double))0, bar_stubs());
class_<Y>("Y", init<>("doc of Y init")) // this should work
.def("get_state", &Y::get_state)
.def("get_state", &Y::get_state)
;
class_<X>("X")

View File

@@ -11,6 +11,7 @@
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <stdexcept>
#include <cassert>
namespace python = boost::python;
@@ -68,13 +69,13 @@ void test()
Py_Initialize();
// Retrieve the main module
python::handle<> main_module(
python::borrowed(PyImport_AddModule("__main__")) );
// Retrieve the main modules namespace
python::handle<> main_namespace(
python::borrowed(PyModule_GetDict(main_module.get())) );
python::object main_module = python::extract<python::object>(
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(
@@ -83,7 +84,7 @@ void test()
"class PythonDerived(Base): \n"
" def hello(self): \n"
" return 'Hello from Python!' \n",
Py_file_input, main_namespace.get(), main_namespace.get())
Py_file_input, main_namespace.ptr(), main_namespace.ptr())
);
// Result is not needed
result.reset();
@@ -91,7 +92,7 @@ void test()
// Extract the raw Python object representing the just defined derived class
python::handle<> class_ptr(
PyRun_String("PythonDerived\n", Py_eval_input,
main_namespace.get(), main_namespace.get()) );
main_namespace.ptr(), main_namespace.ptr()) );
// Wrap the raw Python object in a Boost.Python object
python::object PythonDerived(class_ptr);

View File

@@ -56,6 +56,11 @@ struct Bar
n_ = n;
}
void seta(int a)
{
a_ = a;
}
int geta() const { return a_; }
double getb() const { return b_; }
@@ -71,37 +76,36 @@ private:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(bar_set, Bar::set, 0,3)
using namespace boost::python;
#if BOOST_WORKAROUND(__GNUC__, == 2)
using boost::python::arg;
#endif
BOOST_PYTHON_MODULE(keywords)
{
class_<Foo>("Foo" , init<
int
, double
, const std::string &
>(
( arg("a") = 0
, arg("b") = 0.0
, arg("n") = std::string()
)
))
#if BOOST_WORKAROUND(__GNUC__, == 2)
using boost::python::arg;
#endif
class_<Foo>(
"Foo"
, init<int, double, const std::string&>(
( arg("a") = 0
, arg("b") = 0.0
, arg("n") = std::string()
)
))
.def("set", &Foo::set, (arg("a") = 0, arg("b") = 0.0, arg("n") = std::string()) )
.def("set2", &Foo::set, (arg("a"), "b", "n") )
.def("a", &Foo::geta)
.def("b", &Foo::getb)
.def("n", &Foo::getn)
;
class_<Bar>("Bar" , init<optional<
int
, double
, const std::string &
>
>()
)
class_<Bar>("Bar"
, init<optional<int, double, const std::string &> >()
)
.def("set", &Bar::set, bar_set())
.def("seta", &Bar::seta, arg("a"))
.def("a", &Bar::geta)
.def("b", &Bar::getb)
.def("n", &Bar::getn)

View File

@@ -48,6 +48,9 @@
>>> f.set(1,n="1")
>>> f.a(), f.b(), f.n()
(1, 0.0, '1')
>>> f.set2(b=2.0,n="2",a=2)
>>> f.a(), f.b(), f.n()
(2, 2.0, '2')
# lets see how badly we've broken the 'regular' functions
>>> f = Bar()

View File

@@ -134,6 +134,9 @@ bool check_string_slice()
if (s.slice(-3,_) != "rld")
return false;
if (s.slice(_,_) != s)
return false;
if (", " != s.slice(5,7))
return false;

View File

@@ -1,8 +1,8 @@
'''
>>> from object_ext import *
>>> class(ref_to_noncopyable())
object_ext.NotCopyable
>>> type(ref_to_noncopyable())
<class 'object_ext.NotCopyable'>
>>> def print1(x):
... print x

View File

@@ -18,8 +18,14 @@
// trouble for non-conforming compilers and libraries.
#include <math.h>
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
// vc7.1 seems to require this (incorrectly) in order to use the "not" keyword
#include <ciso646>
#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|| BOOST_WORKAROUND(__GNUC__, <= 2) \
|| BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
#define not !
#endif
using namespace boost::python;

41
test/pickle4.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Example by Ralf W. Grosse-Kunstleve
/*
This example shows how to enable pickling without using the
pickle_suite. The pickling interface (__getinitargs__) is
implemented in Python.
For more information refer to boost/libs/python/doc/pickle.html.
*/
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <string>
namespace {
// A friendly class.
class world
{
private:
std::string country;
public:
world(const std::string& country) {
this->country = country;
}
std::string greet() const { return "Hello from " + country + "!"; }
std::string get_country() const { return country; }
};
}
BOOST_PYTHON_MODULE(pickle4_ext)
{
using namespace boost::python;
class_<world>("world", init<const std::string&>())
.enable_pickling()
.def("greet", &world::greet)
.def("get_country", &world::get_country)
;
}

36
test/pickle4.py Normal file
View File

@@ -0,0 +1,36 @@
r'''>>> import pickle4_ext
>>> import pickle
>>> def world_getinitargs(self):
... return (self.get_country(),)
>>> pickle4_ext.world.__getinitargs__ = world_getinitargs
>>> pickle4_ext.world.__module__
'pickle4_ext'
>>> pickle4_ext.world.__safe_for_unpickling__
1
>>> pickle4_ext.world.__name__
'world'
>>> pickle4_ext.world('Hello').__reduce__()
(<class 'pickle4_ext.world'>, ('Hello',))
>>> wd = pickle4_ext.world('California')
>>> pstr = pickle.dumps(wd)
>>> wl = pickle.loads(pstr)
>>> print wd.greet()
Hello from California!
>>> print wl.greet()
Hello from California!
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
status = run()[0]
if (status == 0): print "Done."
sys.exit(status)

View File

@@ -2,6 +2,26 @@
using namespace boost::python;
namespace test {
// Hmm. return_internal_reference<>() wants to wrap a real class.
class ret_type
{
public:
ret_type() : i(42.5) {}
double i;
};
class crash_me
{
private:
ret_type i;
public:
ret_type& get_i() { return i; }
};
}
struct X
{
X( int value ) : m_value( value )
@@ -55,6 +75,20 @@ BOOST_PYTHON_MODULE(properties_ext)
make_setter( &X::s_count, return_by_internal_reference_t() ) )
//defining class property using a global function
.add_static_property( "instance_count_injected", &get_X_instance_count );
class_< test::ret_type>( "ret_type")
.add_property( "i", &test::ret_type::i, &test::ret_type::i)
;
class_< test::crash_me> crash_me_wrapper( "crash_me");
crash_me_wrapper
.def( "get_i", &test::crash_me::get_i , return_internal_reference<>())
;
crash_me_wrapper.add_property( "i", crash_me_wrapper.attr("get_i"));
}
#include "module_tail.cpp"

View File

@@ -1,5 +1,13 @@
"""
This is test module for properies.
This is test module for properties.
>>> r = properties.ret_type()
>>> r.i = 22.5
>>> r.i
22.5
>>> c = properties.crash_me()
>>> c.i.i
42.5
>>> X = properties.X

83
test/slice.cpp Normal file
View File

@@ -0,0 +1,83 @@
#include <boost/python.hpp>
#include <boost/python/slice.hpp>
using namespace boost::python;
// These checks are only valid under Python 2.3
// (rich slicing wasn't supported for builtins under Python 2.2)
bool check_string_rich_slice()
{
object s("hello, world");
// default slice
if (s[slice()] != "hello, world")
return false;
// simple reverse
if (s[slice(_,_,-1)] != "dlrow ,olleh")
return false;
// reverse with mixed-sign offsets
if (s[slice(-6,1,-1)] != " ,oll")
return false;
// all of the object.cpp check_string_slice() checks should work
// with the form that omits the step argument.
if (s[slice(_,-3)] != "hello, wo")
return false;
if (s[slice(-3,_)] != "rld")
return false;
if (", " != s[slice(5,7)])
return false;
return s[slice(2,-1)][slice(1,-1)] == "lo, wor";
}
// These tests work with Python 2.2, but you must have Numeric installed.
bool check_numeric_array_rich_slice()
{
using numeric::array;
object original = array( make_tuple( make_tuple( 11, 12, 13, 14),
make_tuple( 21, 22, 23, 24),
make_tuple( 31, 32, 33, 34),
make_tuple( 41, 42, 43, 44)));
object upper_left_quadrant = array( make_tuple( make_tuple( 11, 12),
make_tuple( 21, 22)));
object odd_cells = array( make_tuple( make_tuple( 11, 13),
make_tuple( 31, 33)));
object even_cells = array( make_tuple( make_tuple( 22, 24),
make_tuple( 42, 44)));
object lower_right_quadrant_reversed = array(
make_tuple( make_tuple(44, 43),
make_tuple(34, 33)));
// The following comments represent equivalent Python expressions used
// to validate the array behavior.
// original[::] == original
if (original[slice()] != original)
return false;
// original[:2,:2] == array( [[11, 12], [21, 22]])
if (original[make_tuple(slice(_,2), slice(_,2))] != upper_left_quadrant)
return false;
// original[::2,::2] == array( [[11, 13], [31, 33]])
if (original[make_tuple( slice(_,_,2), slice(_,_,2))] != odd_cells)
return false;
// original[1::2, 1::2] == array( [[22, 24], [42, 44]])
if (original[make_tuple( slice(1,_,2), slice(1,_,2))] != even_cells)
return false;
// original[:-3:-1, :-3,-1] == array( [[44, 43], [34, 33]])
if (original[make_tuple( slice(_,-3,-1), slice(_,-3,-1))] != lower_right_quadrant_reversed)
return false;
return true;
}
// Verify functions accepting a slice argument can be called
bool accept_slice( slice) { return true; }
BOOST_PYTHON_MODULE(slice_ext)
{
def( "accept_slice", accept_slice);
def( "check_numeric_array_rich_slice", check_numeric_array_rich_slice);
def( "check_string_rich_slice", check_string_rich_slice);
}

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