mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
81 Commits
boost-0.9.
...
svn-tags/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2e04cd704 | ||
|
|
a9c2a95366 | ||
|
|
29f3891a68 | ||
|
|
7b602ef607 | ||
|
|
15e555c7f1 | ||
|
|
f4fb49d32f | ||
|
|
89be2fb736 | ||
|
|
62f0885852 | ||
|
|
355e155e69 | ||
|
|
ae1584ff3c | ||
|
|
4a7686cd33 | ||
|
|
799eeb0cb8 | ||
|
|
8452e275d0 | ||
|
|
53268000e7 | ||
|
|
52febfe3fc | ||
|
|
8fcfed495a | ||
|
|
2dfe76b082 | ||
|
|
11d8751d29 | ||
|
|
b03c3a29e0 | ||
|
|
53e8982e05 | ||
|
|
4a30841ad8 | ||
|
|
234ebadb8d | ||
|
|
11ee20fa36 | ||
|
|
440599545f | ||
|
|
44ba088cb4 | ||
|
|
08d3798722 | ||
|
|
56ff8e438e | ||
|
|
3590a3589d | ||
|
|
7674c82e1f | ||
|
|
b93b21a7f2 | ||
|
|
f53925848c | ||
|
|
eedc88b56a | ||
|
|
1102fec2a0 | ||
|
|
589fefe4b9 | ||
|
|
cfc867bd18 | ||
|
|
5bc28e3016 | ||
|
|
23b7ccca7f | ||
|
|
e9d6286a1d | ||
|
|
48321857e4 | ||
|
|
156da15715 | ||
|
|
4a0d7965cb | ||
|
|
1f522823ff | ||
|
|
6795a280fd | ||
|
|
f369e22638 | ||
|
|
a278da2eba | ||
|
|
37b2bdba79 | ||
|
|
e9519db974 | ||
|
|
dd7a24ebce | ||
|
|
bc92a7d155 | ||
|
|
a68db84df6 | ||
|
|
7b9bba3190 | ||
|
|
bcec0af232 | ||
|
|
0d437c4102 | ||
|
|
feff7bccd3 | ||
|
|
b12de3f01b | ||
|
|
0d108f12e4 | ||
|
|
4aca2ca33b | ||
|
|
9a967ae514 | ||
|
|
9481c39874 | ||
|
|
1e02065982 | ||
|
|
1fee0da689 | ||
|
|
c760cf8418 | ||
|
|
cdee5997af | ||
|
|
4289280cdc | ||
|
|
962dfa17c5 | ||
|
|
0a21aef601 | ||
|
|
8cbbd504cf | ||
|
|
91b23c8367 | ||
|
|
3729be263f | ||
|
|
ea91f4217a | ||
|
|
7fab3ce0b1 | ||
|
|
ef7d675d67 | ||
|
|
2b9d29a0fc | ||
|
|
95b95d012c | ||
|
|
4af7d5bca7 | ||
|
|
d879eb235f | ||
|
|
4f129d035b | ||
|
|
7a354c4ff4 | ||
|
|
364826b3b3 | ||
|
|
e9b308da46 | ||
|
|
94cfa2602f |
@@ -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
|
||||
@@ -85,4 +87,8 @@ if [ check-python-config ]
|
||||
:
|
||||
debug release
|
||||
;
|
||||
}
|
||||
|
||||
install python lib
|
||||
: <dll>boost_python <lib>boost_python
|
||||
;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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>
|
||||
|
||||
@@ -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>© Copyright <a href="../../people/dave_abrahams.htm">Dave
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
|
||||
@@ -108,7 +108,7 @@ BOOST_PYTHON_MODULE(test)
|
||||
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||
Ganß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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 "the one and only way".
|
||||
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 "I can't build Boost.Python" 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 "the one and only way".
|
||||
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 "I can't build Boost.Python" problems come from people
|
||||
who had to use a different tool.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
|
||||
210
doc/tutorial/doc/creating_packages.html
Normal file
210
doc/tutorial/doc/creating_packages.html
Normal 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>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>io
|
||||
</span><span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sound </span><span class=special>= </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>io</span><span class=special>.</span><span class=identifier>open</span><span class=special>(</span><span class=literal>'file.mp3'</span><span class=special>)
|
||||
>>> </span><span class=identifier>new_sound </span><span class=special>= </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(</span><span class=identifier>sound</span><span class=special>, </span><span class=number>1.0</span><span class=special>)
|
||||
</span></pre></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>>>> </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>>>> </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>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(...)
|
||||
</span></pre></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>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo_noise</span><span class=special>(...)
|
||||
</span></pre></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 © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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
|
||||
|
||||
@@ -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 © 2002-2003 Dirk Gerrits<br><br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
|
||||
@@ -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>
|
||||
|
||||
134
doc/tutorial/doc/extending_wrapped_objects_in_python.html
Normal file
134
doc/tutorial/doc/extending_wrapped_objects_in_python.html
Normal 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>>>> </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>>>>
|
||||
>>> </span>##<span class=identifier>a </span><span class=identifier>regular </span><span class=identifier>function
|
||||
</span><span class=special>>>> </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>>>>
|
||||
>>> </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>>>> </span><span class=identifier>C</span><span class=special>.</span><span class=identifier>__str__ </span><span class=special>= </span><span class=identifier>C_str
|
||||
</span><span class=special>>>>
|
||||
>>> </span><span class=identifier>c </span><span class=special>= </span><span class=identifier>C</span><span class=special>()
|
||||
>>> </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>!
|
||||
>>> </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><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</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 "injects" 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>"point"
|
||||
</span><span class=identifier>BoostPythonMetaclass </span><span class=special>= </span><span class=identifier>point</span><span class=special>.</span><span class=identifier>__class__
|
||||
|
||||
</span><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>>>> </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>)
|
||||
>>> </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 © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
43
doc/tutorial/doc/general_techniques.html
Normal file
43
doc/tutorial/doc/general_techniques.html
Normal 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 © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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.]
|
||||
|
||||
|
||||
115
doc/tutorial/doc/reducing_compiling_time.html
Normal file
115
doc/tutorial/doc/reducing_compiling_time.html
Normal 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><</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
|
||||
</span><span class=keyword>void </span><span class=identifier>export_point</span><span class=special>()
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</span><span class=special>)...;
|
||||
}
|
||||
|
||||
/* </span><span 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><</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
|
||||
</span><span class=keyword>void </span><span class=identifier>export_triangle</span><span class=special>()
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>triangle</span><span class=special>>(</span><span class=string>"triangle"</span><span class=special>)...;
|
||||
}
|
||||
</span></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><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
|
||||
</span><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><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</span><span class=special>)...;
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>triangle</span><span class=special>>(</span><span class=string>"triangle"</span><span class=special>)...;
|
||||
}
|
||||
</span></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>"fatal error C1204:Compiler limit:internal structure overflow"</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 © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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><> </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>"__main__"</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><>(</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><>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>"result = 5 ** 2"</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><</span><span class=keyword>int</span><span class=special>>( </span><span class=identifier>main_namespace</span><span class=special>[</span><span class=string>"result"</span><span class=special>] );
|
||||
</span></pre>
|
||||
</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 © 2002-2003 Dirk Gerrits<br><br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
|
||||
@@ -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 © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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><T>::type*</code>
|
||||
<td><code>&*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>© 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
|
||||
|
||||
@@ -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<...>/right_operand<...></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>
|
||||
|
||||
@@ -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> ("Pie-Steh")
|
||||
code generator.
|
||||
|
||||
@@ -281,6 +281,7 @@ namespace boost { namespace python
|
||||
// pickle support
|
||||
template <typename PickleSuite>
|
||||
self& def_pickle(PickleSuite const&);
|
||||
self& enable_pickling();
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
@@ -709,6 +710,21 @@ class_& def_pickle(PickleSuite const&);
|
||||
checks.</dt>
|
||||
</dl>
|
||||
<br>
|
||||
<pre>
|
||||
class_& 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
|
||||
|
||||
438
doc/v2/faq.html
438
doc/v2/faq.html
@@ -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>
|
||||
>>> def hello(s):
|
||||
... print s
|
||||
... print s
|
||||
...
|
||||
>>> 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& get_floating_frequency() const
|
||||
{
|
||||
@@ -127,7 +142,7 @@ period const& 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_<></code> wrapper:
|
||||
Using the regular <code>class_<></code> wrapper:
|
||||
<pre>
|
||||
class_<std::vector<double> >("std_vector_double")
|
||||
.def(...)
|
||||
@@ -189,13 +204,13 @@ class_<std::vector<double> >("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<> instantiations.
|
||||
wrapping std::vector<> instantiations.
|
||||
|
||||
<p>This type of C++/Python binding is most suitable for containers
|
||||
that may contain a large number of elements (>10000).</p>
|
||||
@@ -203,19 +218,19 @@ class_<std::vector<double> >("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<double> const& array); // pass by const-reference
|
||||
void foo(std::vector<double> 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<> or std::list<> 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<double> 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<> <-> Python list. These converters would
|
||||
@@ -245,7 +260,7 @@ void foo(std::vector<double>& array)
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Python:
|
||||
Python:
|
||||
<pre>
|
||||
>>> l = [1, 2, 3]
|
||||
>>> foo(l)
|
||||
@@ -253,7 +268,7 @@ void foo(std::vector<double>& 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<my_class>& 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 – Native – Cygwin Native –
|
||||
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.
|
||||
>>> ^Z
|
||||
|
||||
|
||||
Program exited normally.
|
||||
(gdb) break *&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.
|
||||
>>> 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_<your_type></tt>
|
||||
template instantiation:
|
||||
<pre>.../inheritance.hpp:44: error: cannot
|
||||
dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::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__) && defined(__APPLE_CC__) && __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_<X,X_wrap>("X", init<int>())
|
||||
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_<X,X_wrap>("X", init<int>())
|
||||
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_<A, std::auto_ptr<A> >("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& b, std::auto_ptr<A> a)
|
||||
{
|
||||
@@ -547,26 +643,237 @@ void b_insert(B& b, std::auto_ptr<A> 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 <boost/python.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
class FXThread
|
||||
{
|
||||
public:
|
||||
bool setAutoDelete(bool doso) throw();
|
||||
};
|
||||
|
||||
void Export_FXThread()
|
||||
{
|
||||
class_< FXThread >("FXThread")
|
||||
.def("setAutoDelete", &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)) &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", &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 <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
namespace sandbox { namespace {
|
||||
|
||||
class custom_string
|
||||
{
|
||||
public:
|
||||
custom_string() {}
|
||||
custom_string(std::string const& value) : value_(value) {}
|
||||
std::string const& value() const { return value_; }
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
struct custom_string_to_python_str
|
||||
{
|
||||
static PyObject* convert(custom_string const& 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(
|
||||
&convertible,
|
||||
&construct,
|
||||
boost::python::type_id<custom_string>());
|
||||
}
|
||||
|
||||
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<custom_string>*)
|
||||
data)->storage.bytes;
|
||||
new (storage) custom_string(value);
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
custom_string hello() { return custom_string("Hello world."); }
|
||||
|
||||
std::size_t size(custom_string const& s) { return s.value().size(); }
|
||||
|
||||
void init_module()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
boost::python::to_python_converter<
|
||||
custom_string,
|
||||
custom_string_to_python_str>();
|
||||
|
||||
custom_string_from_python_str();
|
||||
|
||||
def("hello", hello);
|
||||
def("size", size);
|
||||
}
|
||||
|
||||
}} // namespace sandbox::<anonymous>
|
||||
|
||||
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", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()))</pre>
|
||||
|
||||
Similarly, <tt>def_readwrite("bar", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
|
||||
make_setter(&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(&foo::bar, return_value_policy<return_by_value>()),
|
||||
make_setter(&foo::bar, return_value_policy<return_by_value>()))</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& b, std::auto_ptr<A> a)
|
||||
Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -71,9 +71,8 @@ namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
struct from_python : private <a href=
|
||||
"../../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// from_python<T> meets the <a href=
|
||||
"NonCopyable.html">NonCopyable</a> requirements
|
||||
"../../../utility/utility.htm#Class_noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// from_python<T> meets the NonCopyable requirements
|
||||
{
|
||||
from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
|
||||
@@ -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<<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<<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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -99,7 +99,7 @@ template <class F, class Policies, class Keywords, class Signature>
|
||||
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 <class ArgList, class Generator, class Policies>
|
||||
<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, A2,... AN</i>) such that if
|
||||
<code>a1, a2</code>... <code>aN</code> are objects of type
|
||||
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
||||
|
||||
@@ -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>
|
||||
>>> x[:-1]
|
||||
>>> x[::-1]
|
||||
</pre>
|
||||
C++ equivalent:
|
||||
<pre>
|
||||
x.slice(_,-1)
|
||||
x[slice(_,_,-1)]
|
||||
</pre>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
@@ -281,13 +281,51 @@ is not empty.
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<h2>Light-weight alternative: pickle support implemented in Python</h2>
|
||||
|
||||
© 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_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.enable_pickling()
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
This enables the standard Python pickle interface as described
|
||||
in the Python documentation. By "injecting" 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>
|
||||
|
||||
© 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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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<X></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<X></code>
|
||||
<dt><b>Effects:</b> Allows conversions to-python of <code>P</code>
|
||||
instances.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
@@ -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
241
doc/v2/slice.html
Normal 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 - <boost/python/slice.hpp></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 <boost/python/slice.hpp></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 <typename Int1, typename Int2>
|
||||
slice(Int1 start, Int2 stop);
|
||||
|
||||
template <typename Int1, typename Int2, typename Int3>
|
||||
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 <typename RandomAccessIterator>
|
||||
struct range
|
||||
{
|
||||
RandomAccessIterator start;
|
||||
RandomAccessIterator stop;
|
||||
int step;
|
||||
};
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
range<RandomAccessIterator>
|
||||
get_indicies(
|
||||
RandomAccessIterator const& begin,
|
||||
RandomAccessIterator const& 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. Equivalent to the slice object created by the Python
|
||||
expression <code>base[::].</code></dt>
|
||||
<dt><b>Throws:</b> nothing.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <typename Int1, typename Int2>
|
||||
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. 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 <typename Int1, typename Int2, typename Int3>
|
||||
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. 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. 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. In principal, any object may be used when creating a
|
||||
slice object, but in practice they are usually integers.</dt>
|
||||
</dl>
|
||||
<br>
|
||||
<pre>
|
||||
template <typename RandomAccessIterator>
|
||||
slice::range<RandomAccessIterator>
|
||||
slice::get_indicies(
|
||||
RandomAccessIterator const& begin, RandomAccessIterator const& 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.
|
||||
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>. Throws
|
||||
<code>std::invalid_argument</code> if the resulting range would be empty. 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. 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<double> const& Foo, slice index)
|
||||
{
|
||||
slice::range<std::vector<double>::const_iterator> bounds;
|
||||
try {
|
||||
bounds = index.get_indicies<>(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>© Copyright <a
|
||||
href="mailto:jbrandmeyer@users.sourceforge.net">Jonathan Brandmeyer</a>,
|
||||
2004. 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>
|
||||
@@ -60,8 +60,8 @@ namespace boost { namespace python
|
||||
template <class T>
|
||||
struct to_python_value
|
||||
{
|
||||
typedef typename <a href="../../../type_traits/index.htm#transformations">add_reference</a><
|
||||
typename <a href="../../../type_traits/index.htm#transformations">add_const</a><T>::type
|
||||
typedef typename <a href="../../../type_traits/index.html#transformations">add_reference</a><
|
||||
typename <a href="../../../type_traits/index.html#transformations">add_const</a><T>::type
|
||||
>::type argument_type;
|
||||
|
||||
static bool convertible();
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 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;
|
||||
@@ -476,6 +517,7 @@ class class_ : public objects::class_base
|
||||
// These two overloads discriminate between def() as applied to a
|
||||
// generic visitor and everything else.
|
||||
//
|
||||
// @group def_impl {
|
||||
template <class Helper, class LeafVisitor, class Visitor>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
@@ -509,12 +551,14 @@ class class_ : public objects::class_base
|
||||
|
||||
this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
|
||||
}
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads handle the definition of default
|
||||
// implementation overloads for virtual functions. The second one
|
||||
// handles the case where no default implementation was specified.
|
||||
//
|
||||
// @group def_default {
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(
|
||||
char const* name
|
||||
@@ -535,6 +579,7 @@ class class_ : public objects::class_base
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
|
||||
{ }
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to
|
||||
@@ -542,6 +587,7 @@ class class_ : public objects::class_base
|
||||
// BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
|
||||
// discriminate.
|
||||
//
|
||||
// @group def_maybe_overloads {
|
||||
template <class OverloadsT, class SigT>
|
||||
void def_maybe_overloads(
|
||||
char const* name
|
||||
@@ -571,6 +617,7 @@ class class_ : public objects::class_base
|
||||
);
|
||||
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>))
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace detail
|
||||
//
|
||||
// Dispatch to properly add f to namespace ns.
|
||||
//
|
||||
// { define_stub_function helpers
|
||||
// @group define_stub_function helpers {
|
||||
template <class Func, class CallPolicies, class NameSpaceT>
|
||||
static void name_space_def(
|
||||
NameSpaceT& name_space
|
||||
@@ -122,7 +122,7 @@ namespace detail
|
||||
// (see defaults_gen.hpp)
|
||||
// 5. char const* name: doc string
|
||||
//
|
||||
// {
|
||||
// @group define_stub_function<N> {
|
||||
template <int N>
|
||||
struct define_stub_function {};
|
||||
|
||||
|
||||
@@ -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_ \
|
||||
{ \
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace boost { namespace python { namespace detail {
|
||||
// arguments, because compile-time information about the number of
|
||||
// keywords is missing for all but the initial function definition.
|
||||
//
|
||||
// {
|
||||
// @group make_keyword_range_function {
|
||||
template <class F, class Policies>
|
||||
object make_keyword_range_function(
|
||||
F f
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# if BOOST_PYTHON_MAX_ARITY + 2 > BOOST_PYTHON_MAX_BASES
|
||||
# define BOOST_PYTHON_LIST_SIZE BOOST_PP_INC(BOOST_PP_INC(BOOST_PYTHON_MAX_ARITY))
|
||||
# else
|
||||
# define BOOST_PYTHON_BASE_LIST_SIZE BOOST_PYTHON_MAX_BASES
|
||||
# define BOOST_PYTHON_LIST_SIZE BOOST_PYTHON_MAX_BASES
|
||||
# endif
|
||||
|
||||
// Compute the MPL vector header to use for lists up to BOOST_PYTHON_LIST_SIZE in length
|
||||
|
||||
@@ -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;
|
||||
|
||||
//
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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_)
|
||||
@@ -138,12 +130,13 @@ namespace detail
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
// { make_constructor_aux
|
||||
//
|
||||
// These helper functions for make_constructor (below) do the raw work
|
||||
// of constructing a Python object from some invokable entity. See
|
||||
// <boost/python/detail/caller.hpp> for more information about how
|
||||
// the Sig arguments is used.
|
||||
//
|
||||
// @group make_constructor_aux {
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
object make_constructor_aux(
|
||||
F f // An object that can be invoked by detail::invoke()
|
||||
@@ -195,10 +188,12 @@ namespace detail
|
||||
}
|
||||
// }
|
||||
|
||||
|
||||
// { Helpers for make_constructor when called with 3 arguments. These
|
||||
// dispatch functions are used to discriminate between the cases
|
||||
// when the 3rd argument is keywords or when it is a signature.
|
||||
//
|
||||
// These dispatch functions are used to discriminate between the
|
||||
// cases when the 3rd argument is keywords or when it is a
|
||||
// signature.
|
||||
//
|
||||
// @group Helpers for make_constructor when called with 3 arguments. {
|
||||
//
|
||||
template <class F, class CallPolicies, class Keywords>
|
||||
object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
|
||||
@@ -224,9 +219,10 @@ namespace detail
|
||||
// }
|
||||
}
|
||||
|
||||
// { These overloaded functions wrap a function or member function
|
||||
// These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies,
|
||||
// Keywords, and/or Signature.
|
||||
// Keywords, and/or Signature. @group {
|
||||
//
|
||||
template <class F>
|
||||
object make_constructor(F f)
|
||||
{
|
||||
|
||||
@@ -63,10 +63,11 @@ namespace detail
|
||||
, kw);
|
||||
}
|
||||
|
||||
// { Helpers for make_function when called with 3 arguments. These
|
||||
// Helpers for make_function when called with 3 arguments. These
|
||||
// dispatch functions are used to discriminate between the cases
|
||||
// when the 3rd argument is keywords or when it is a signature.
|
||||
//
|
||||
// @group {
|
||||
template <class F, class CallPolicies, class Keywords>
|
||||
object make_function_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
|
||||
{
|
||||
@@ -92,9 +93,11 @@ namespace detail
|
||||
|
||||
}
|
||||
|
||||
// { These overloaded functions wrap a function or member function
|
||||
// These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies,
|
||||
// Keywords, and/or Signature.
|
||||
//
|
||||
// @group {
|
||||
template <class F>
|
||||
object make_function(F f)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -280,7 +283,7 @@ namespace api
|
||||
return object_initializer<
|
||||
BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
|
||||
>::get(
|
||||
api::do_unforward_cref(x)
|
||||
x
|
||||
, is_obj()
|
||||
);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -17,29 +17,28 @@
|
||||
|
||||
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&);
|
||||
template <class X>
|
||||
char is_object_operators_helper(object_operators<X> const*);
|
||||
|
||||
typedef char (&no_type)[2];
|
||||
no_type is_object_operators_helper(...);
|
||||
|
||||
template <class X> X& make();
|
||||
template <class X> X* make_ptr();
|
||||
|
||||
template <class L, class R>
|
||||
template <class L, class R = L>
|
||||
struct is_object_operators
|
||||
{
|
||||
enum {
|
||||
value
|
||||
= (sizeof(api::is_object_operators_helper(api::make<L>()))
|
||||
+ sizeof(api::is_object_operators_helper(api::make<R>()))
|
||||
= (sizeof(api::is_object_operators_helper(api::make_ptr<L>()))
|
||||
+ sizeof(api::is_object_operators_helper(api::make_ptr<R>()))
|
||||
< 4
|
||||
)
|
||||
};
|
||||
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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -133,4 +133,4 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
|
||||
} \
|
||||
}}
|
||||
# endif
|
||||
# endif // OPAQUE_POINTER_CONVERTER_HPP_
|
||||
# endif // OPAQUE_POINTER_CONVERTER_HPP_
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace boost { namespace python {
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// { Helpers for pure_virtual_visitor, below.
|
||||
// @group Helpers for pure_virtual_visitor. {
|
||||
//
|
||||
|
||||
// Raises a Python RuntimeError reporting that a pure virtual
|
||||
@@ -55,7 +55,7 @@ namespace detail
|
||||
}
|
||||
|
||||
//
|
||||
// } Helpers for pure_virtual_visitor
|
||||
// }
|
||||
//
|
||||
|
||||
//
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ struct most_derived
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// {
|
||||
// The following macros generate expansions for::
|
||||
//
|
||||
// template <class RT, class T0... class TN>
|
||||
@@ -99,6 +98,8 @@ struct most_derived
|
||||
// this" argument of member functions to Target, because the function
|
||||
// may actually be a member of a base class which is not wrapped, and
|
||||
// in that case conversion from python would fail.
|
||||
//
|
||||
// @group {
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
|
||||
|
||||
252
include/boost/python/slice.hpp
Normal file
252
include/boost/python/slice.hpp
Normal 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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
# include <typeinfo>
|
||||
# include <cstring>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# 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
|
||||
@@ -67,7 +69,9 @@ template <class T>
|
||||
inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T))
|
||||
{
|
||||
return type_info(
|
||||
# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 700)
|
||||
# if !defined(_MSC_VER) \
|
||||
|| (!BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||
&& !BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700))
|
||||
typeid(T)
|
||||
# else // strip the decoration which msvc and Intel mistakenly leave in
|
||||
python::detail::msvc_typeid((boost::type<T>*)0)
|
||||
@@ -75,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
23 October 2003
|
||||
Fixed bug where a class would appear more than one in the generated code.
|
||||
|
||||
6 October 2003
|
||||
Fixed bug reported by Niall Douglas (using his patch) about UniqueInt not
|
||||
appearing correctly with --multiple.
|
||||
|
||||
@@ -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')
|
||||
@@ -598,7 +599,7 @@ class ClassExporter(Exporter):
|
||||
nested_info = self.info[nested_class.name]
|
||||
nested_info.include = self.info.include
|
||||
nested_info.name = nested_class.FullName()
|
||||
exporter = ClassExporter(nested_info)
|
||||
exporter = self.__class__(nested_info)
|
||||
exporter.SetDeclarations(self.declarations)
|
||||
codeunit = SingleCodeUnit(None, None)
|
||||
exporter.Export(codeunit, exported_names)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -17,6 +17,7 @@ class SingleCodeUnit:
|
||||
Represents a cpp file, where other objects can write in one of the
|
||||
predefined sections.
|
||||
The avaiable sections are:
|
||||
pchinclude - The pre-compiled header area
|
||||
include - The include area of the cpp file
|
||||
declaration - The part before the module definition
|
||||
module - Inside the BOOST_PYTHON_MODULE macro
|
||||
@@ -28,6 +29,8 @@ class SingleCodeUnit:
|
||||
# define the avaiable sections
|
||||
self.code = {}
|
||||
# include section
|
||||
self.code['pchinclude'] = ''
|
||||
# include section
|
||||
self.code['include'] = ''
|
||||
# declaration section (inside namespace)
|
||||
self.code['declaration'] = ''
|
||||
@@ -74,15 +77,17 @@ class SingleCodeUnit:
|
||||
fout.write('\n')
|
||||
# includes
|
||||
# boost.python header
|
||||
fout.write(left_equals('Boost Includes'))
|
||||
fout.write('#include <boost/python.hpp>\n')
|
||||
# include numerical boost for int64 definitions
|
||||
fout.write('#include <boost/cstdint.hpp>\n')
|
||||
if settings.msvc:
|
||||
# include precompiled header directive
|
||||
if self.code['pchinclude']:
|
||||
fout.write(left_equals('PCH'))
|
||||
fout.write(self.code['pchinclude']+'\n')
|
||||
fout.write('#ifdef _MSC_VER\n')
|
||||
fout.write('#pragma hdrstop\n')
|
||||
fout.write('#endif\n')
|
||||
fout.write('#endif\n')
|
||||
else:
|
||||
fout.write(left_equals('Boost Includes'))
|
||||
fout.write('#include <boost/python.hpp>\n')
|
||||
# include numerical boost for int64 definitions
|
||||
fout.write('#include <boost/cstdint.hpp>\n')
|
||||
fout.write('\n')
|
||||
# other includes
|
||||
if self.code['include']:
|
||||
|
||||
@@ -8,3 +8,5 @@
|
||||
exporters = []
|
||||
|
||||
current_interface = None # the current interface file being processed
|
||||
importing = False # whetever we are now importing a pyste file.
|
||||
# exporters created here shouldn't export themselves
|
||||
|
||||
@@ -14,7 +14,7 @@ from VarExporter import VarExporter
|
||||
from CodeExporter import CodeExporter
|
||||
from exporterutils import FunctionWrapper
|
||||
from utils import makeid
|
||||
|
||||
import warnings
|
||||
|
||||
#==============================================================================
|
||||
# DeclarationInfo
|
||||
@@ -51,21 +51,27 @@ class DeclarationInfo:
|
||||
self.__attributes[name] = value
|
||||
|
||||
|
||||
def AddExporter(self, exporter):
|
||||
if not exporters.importing:
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# FunctionInfo
|
||||
#==============================================================================
|
||||
class FunctionInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, name, include, tail=None, otherOption=None):
|
||||
def __init__(self, name, include, tail=None, otherOption=None,
|
||||
exporter_class = FunctionExporter):
|
||||
DeclarationInfo.__init__(self, otherOption)
|
||||
self._Attribute('name', name)
|
||||
self._Attribute('include', include)
|
||||
self._Attribute('exclude', False)
|
||||
# create a FunctionExporter
|
||||
exporter = FunctionExporter(InfoWrapper(self), tail)
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self), tail)
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@@ -73,16 +79,15 @@ class FunctionInfo(DeclarationInfo):
|
||||
#==============================================================================
|
||||
class ClassInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, name, include, tail=None, otherInfo=None):
|
||||
def __init__(self, name, include, tail=None, otherInfo=None,
|
||||
exporter_class = ClassExporter):
|
||||
DeclarationInfo.__init__(self, otherInfo)
|
||||
self._Attribute('name', name)
|
||||
self._Attribute('include', include)
|
||||
self._Attribute('exclude', False)
|
||||
# create a ClassExporter
|
||||
exporter = ClassExporter(InfoWrapper(self), tail)
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self), tail)
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@@ -96,10 +101,12 @@ def GenerateName(name, type_list):
|
||||
|
||||
class ClassTemplateInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, name, include):
|
||||
def __init__(self, name, include,
|
||||
exporter_class = ClassExporter):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('name', name)
|
||||
self._Attribute('include', include)
|
||||
self._exporter_class = exporter_class
|
||||
|
||||
|
||||
def Instantiate(self, type_list, rename=None):
|
||||
@@ -111,7 +118,8 @@ class ClassTemplateInfo(DeclarationInfo):
|
||||
tail += 'void __instantiate_%s()\n' % rename
|
||||
tail += '{ sizeof(%s); }\n\n' % rename
|
||||
# create a ClassInfo
|
||||
class_ = ClassInfo(rename, self._Attribute('include'), tail, self)
|
||||
class_ = ClassInfo(rename, self._Attribute('include'), tail, self,
|
||||
exporter_class = self._exporter_class)
|
||||
return class_
|
||||
|
||||
|
||||
@@ -125,16 +133,14 @@ class ClassTemplateInfo(DeclarationInfo):
|
||||
#==============================================================================
|
||||
class EnumInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, name, include):
|
||||
def __init__(self, name, include, exporter_class = EnumExporter):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('name', name)
|
||||
self._Attribute('include', include)
|
||||
self._Attribute('exclude', False)
|
||||
self._Attribute('export_values', False)
|
||||
exporter = EnumExporter(InfoWrapper(self))
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self))
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@@ -142,13 +148,12 @@ class EnumInfo(DeclarationInfo):
|
||||
#==============================================================================
|
||||
class HeaderInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, include):
|
||||
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 = HeaderExporter(InfoWrapper(self))
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self))
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@@ -156,14 +161,12 @@ class HeaderInfo(DeclarationInfo):
|
||||
#==============================================================================
|
||||
class VarInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, name, include):
|
||||
def __init__(self, name, include, exporter_class = VarExporter):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('name', name)
|
||||
self._Attribute('include', include)
|
||||
exporter = VarExporter(InfoWrapper(self))
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self))
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@@ -171,14 +174,12 @@ class VarInfo(DeclarationInfo):
|
||||
#==============================================================================
|
||||
class CodeInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, code, section):
|
||||
def __init__(self, code, section, exporter_class = CodeExporter):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('code', code)
|
||||
self._Attribute('section', section)
|
||||
exporter = CodeExporter(InfoWrapper(self))
|
||||
if exporter not in exporters.exporters:
|
||||
exporters.exporters.append(exporter)
|
||||
exporter.interface_file = exporters.current_interface
|
||||
exporter = exporter_class(InfoWrapper(self))
|
||||
self.AddExporter(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
|
||||
@@ -51,7 +51,7 @@ from CppParser import CppParser, CppParserError
|
||||
import time
|
||||
import declarations
|
||||
|
||||
__version__ = '0.9.27'
|
||||
__version__ = '0.9.29'
|
||||
|
||||
def RecursiveIncludes(include):
|
||||
'Return a list containg the include dir and all its subdirectories'
|
||||
@@ -182,15 +182,21 @@ def ParseArguments():
|
||||
ProcessIncludes(includes)
|
||||
return includes, defines, module, out, files, multiple, cache_dir, create_cache, generate_main
|
||||
|
||||
|
||||
def PCHInclude(*headers):
|
||||
code = '\n'.join(['#include <%s>' % x for x in headers])
|
||||
infos.CodeInfo(code, 'pchinclude')
|
||||
|
||||
|
||||
def CreateContext():
|
||||
'create the context where a interface file will be executed'
|
||||
context = {}
|
||||
context['Import'] = ExecuteInterface
|
||||
context['Import'] = Import
|
||||
# infos
|
||||
context['Function'] = infos.FunctionInfo
|
||||
context['Class'] = infos.ClassInfo
|
||||
context['Include'] = lambda header: infos.CodeInfo('#include <%s>\n' % header, 'include')
|
||||
context['PCHInclude'] = PCHInclude
|
||||
context['Template'] = infos.ClassTemplateInfo
|
||||
context['Enum'] = infos.EnumInfo
|
||||
context['AllFromHeader'] = infos.HeaderInfo
|
||||
@@ -279,6 +285,12 @@ def ExecuteInterface(interface):
|
||||
execfile(interface, context)
|
||||
exporters.current_interface = old_interface
|
||||
|
||||
|
||||
def Import(interface):
|
||||
exporters.importing = True
|
||||
ExecuteInterface(interface)
|
||||
exporters.importing = False
|
||||
|
||||
|
||||
def JoinTails(exports):
|
||||
'''Returns a dict of {(interface, header): tail}, where tail is the
|
||||
|
||||
@@ -44,7 +44,9 @@ def makeid(name):
|
||||
def remove_duplicated_lines(text):
|
||||
includes = text.splitlines()
|
||||
d = dict([(include, 0) for include in includes])
|
||||
return '\n'.join(d.keys())
|
||||
includes = d.keys()
|
||||
includes.sort()
|
||||
return '\n'.join(includes)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +214,7 @@ namespace
|
||||
|
||||
vertex_t v = add_vertex(full_graph().topology());
|
||||
vertex_t v2 = add_vertex(up_graph().topology());
|
||||
unused_variable(v2);
|
||||
assert(v == v2);
|
||||
return type_index().insert(p, boost::make_tuple(type, v, dynamic_id_function(0)));
|
||||
}
|
||||
|
||||
@@ -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
38
src/slice.cpp
Normal 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
|
||||
242
test/Jamfile
242
test/Jamfile
@@ -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 ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user