mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 16:52:15 +00:00
Compare commits
131 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 | ||
|
|
3533bd0504 | ||
|
|
1a51a7df9e | ||
|
|
615be89951 | ||
|
|
912ca36a1f | ||
|
|
fba93805dc | ||
|
|
96d66f4624 | ||
|
|
c3bae63e41 | ||
|
|
6c22aceabc | ||
|
|
92a77dfe7f | ||
|
|
4f2dbeda28 | ||
|
|
bec2de08fe | ||
|
|
db192e1e01 | ||
|
|
454654a9cc | ||
|
|
1018bc56eb | ||
|
|
f920dc87d0 | ||
|
|
8b97caae46 | ||
|
|
3b74aab818 | ||
|
|
e78b4939b3 | ||
|
|
621b5fc2db | ||
|
|
6ada069d5a | ||
|
|
50db384be1 | ||
|
|
ae7225ae83 | ||
|
|
911ba333a2 | ||
|
|
5cd8cce531 | ||
|
|
6a2a76cea9 | ||
|
|
7a9a3d30c9 | ||
|
|
034ca4d5eb | ||
|
|
00e3fa32fb | ||
|
|
0133bdfbe3 | ||
|
|
e563def5ba | ||
|
|
b3910f4e4d | ||
|
|
4a7b8fe839 | ||
|
|
fc56544da4 | ||
|
|
c839d25722 | ||
|
|
c6b5ecbbdb | ||
|
|
d3473afa23 | ||
|
|
379b28eb85 | ||
|
|
7f5bd33ead | ||
|
|
eef6fb9891 | ||
|
|
4a7f52ab2c | ||
|
|
10b249a162 | ||
|
|
5fc5fce663 | ||
|
|
f00fe3c0b1 | ||
|
|
3047d51613 | ||
|
|
f9f7146960 | ||
|
|
ca9dc3103a | ||
|
|
c03afa379c | ||
|
|
cbacc98e3f | ||
|
|
84daf14f1b | ||
|
|
4af28b2a46 |
@@ -10,8 +10,7 @@
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include <module@>python.jam ;
|
||||
import python ;
|
||||
|
||||
if [ check-python-config ]
|
||||
{
|
||||
@@ -35,6 +34,7 @@ if [ check-python-config ]
|
||||
dict.cpp
|
||||
tuple.cpp
|
||||
str.cpp
|
||||
slice.cpp
|
||||
|
||||
aix_init_module.cpp
|
||||
converter/from_python.cpp
|
||||
@@ -61,8 +61,14 @@ if [ check-python-config ]
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
<darwin><*><linkflags>-bind_at_load
|
||||
;
|
||||
|
||||
template extension
|
||||
: <dll>boost_python
|
||||
: <sysinclude>../../..
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
../src/$(sources)
|
||||
@@ -81,4 +87,8 @@ if [ check-python-config ]
|
||||
:
|
||||
debug release
|
||||
;
|
||||
}
|
||||
|
||||
install python lib
|
||||
: <dll>boost_python <lib>boost_python
|
||||
;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import os ;
|
||||
import modules ;
|
||||
|
||||
# Use a very crude way to sense there python is locatted
|
||||
|
||||
local PYTHON_PATH ;
|
||||
|
||||
local PYTHON_PATH = [ modules.peek : PYTHON_PATH ] ;
|
||||
ECHO "XXX" $(PYTHON_PATH) ;
|
||||
|
||||
if [ GLOB /usr/local/include/python2.2 : * ]
|
||||
{
|
||||
@@ -19,7 +22,7 @@ if [ os.name ] in CYGWIN NT
|
||||
defines = USE_DL_IMPORT ;
|
||||
|
||||
# Declare a target for the python interpreter library
|
||||
lib python : : <name>python2.2.dll ;
|
||||
lib python : : <name>python22 <search>$(PYTHON_PATH)/libs ;
|
||||
PYTHON_LIB = python ;
|
||||
}
|
||||
else
|
||||
@@ -35,12 +38,12 @@ if $(PYTHON_PATH) {
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
: requirements <include>$(PYTHON_PATH)/include/python2.2
|
||||
$(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
: requirements <include>$(PYTHON_PATH)/include
|
||||
$(lib_condition)<library-path>$(PYTHON_PATH)/libs
|
||||
<link>shared:<library>$(PYTHON_LIB)
|
||||
<define>$(defines)
|
||||
: usage-requirements # requirement that will be propageted to *users* of this library
|
||||
<include>$(PYTHON_PATH)/include/python2.2
|
||||
<include>$(PYTHON_PATH)/include
|
||||
|
||||
# We have a bug which causes us to conclude that conditionalized
|
||||
# properties in this section are not free.
|
||||
|
||||
Binary file not shown.
@@ -55,15 +55,6 @@
|
||||
|
||||
<dt><a href="#building_ext">Building your Extension Module</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt><a href="#easy">The Easy Way</a></dt>
|
||||
|
||||
<dt><a href="#outside">Building your module outside the Boost
|
||||
project tree</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#variants">Build Variants</a></dt>
|
||||
|
||||
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
||||
@@ -83,10 +74,10 @@
|
||||
<p>Normally, Boost.Python extension modules must be linked with the
|
||||
<code>boost_python</code> shared library. In special circumstances you
|
||||
may want to link to a static version of the <code>boost_python</code>
|
||||
library, but if multiple Boost.Pythone extension modules are used
|
||||
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>
|
||||
@@ -258,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
|
||||
@@ -268,58 +259,62 @@ 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
|
||||
passes.
|
||||
|
||||
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
||||
Though there are other approaches, the best way to build an extension
|
||||
module using Boost.Python is with Boost.Build. If you have to use another
|
||||
build system, you should use Boost.Build at least once with the
|
||||
Though there are other approaches, the smoothest and most reliable
|
||||
way to build an extension module using Boost.Python is with
|
||||
Boost.Build. If you have to use another build system, you should
|
||||
use Boost.Build at least once with the
|
||||
"<code><b>-n</b></code>" option so you can see the command-lines it uses,
|
||||
and replicate them. You are likely to run into compilation or linking
|
||||
problems otherwise.
|
||||
|
||||
<h3><a name="easy">The Easy Way</a></h3>
|
||||
Until Boost.Build v2 is released, cross-project build dependencies are
|
||||
not supported, so it works most smoothly if you add a new subproject to
|
||||
your boost installation. The <code>libs/python/example</code>
|
||||
subdirectory of your boost installation contains a minimal example (along
|
||||
with many extra sources). To copy the example subproject:
|
||||
The <code><a href="../example">libs/python/example</a></code>
|
||||
subdirectory of your boost installation contains a small example
|
||||
which builds and tests two extensions. To build your own
|
||||
extensions copy the example subproject and make the following two edits:
|
||||
|
||||
<ol>
|
||||
<li>Create a new subdirectory in, <code>libs/python</code>, say
|
||||
<code>libs/python/my_project</code>.</li>
|
||||
<ol>
|
||||
<li><code><a
|
||||
href="../example/boost-build.jam"><b>boost-build.jam</b></a></code> -
|
||||
edit the line which reads
|
||||
|
||||
<li>Copy <code><a href=
|
||||
"../example/Jamfile">libs/python/example/Jamfile</a></code> to your new
|
||||
directory.</li>
|
||||
<blockquote>
|
||||
<pre>
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<li>Edit the Jamfile as appropriate for your project. You'll want to
|
||||
change the "<code>subproject</code>" rule invocation at the top, and
|
||||
the names of some of the source files and/or targets.</li>
|
||||
</ol>
|
||||
so that the path refers to the <code>tools/build/v1</code> subdirectory
|
||||
of your Boost installation.
|
||||
|
||||
|
||||
<li><code><a href="../example/Jamrules"><b>Jamrules</b></a></code> -
|
||||
edit the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the root directory of your Boost installation.
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The instructions <a href="#testing">above</a> for testing Boost.Python
|
||||
apply equally to your new extension modules in this subproject.
|
||||
|
||||
<h3><a name="outside">Building your module outside the Boost project
|
||||
tree</a></h3>
|
||||
If you can't (or don't wish to) modify your boost installation, the
|
||||
alternative is to create your own Boost.Build project. A similar example
|
||||
you can use as a starting point is available in <code><a href=
|
||||
"../example/project.zip">this archive</a></code>. You'll need to edit the
|
||||
Jamfile and Jamrules files, depending on the relative location of your
|
||||
Boost installation and the new project. Note that automatic testing of
|
||||
extension modules is not available in this configuration.
|
||||
|
||||
<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
|
||||
@@ -91,8 +99,10 @@
|
||||
<dt><a href="internals.html">Internals Documentation</a></dt>
|
||||
|
||||
<dt><a href="news.html">News/Change Log</a></dt>
|
||||
|
||||
<dt><a href="../todo.html">TODO list</a></dt>
|
||||
|
||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||
|
||||
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
|
||||
</dl>
|
||||
@@ -108,12 +118,12 @@
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
18 March, 2003
|
||||
26 August, 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></p>
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
|
||||
<title>Boost Python Internals</title>
|
||||
<meta name="copyright" content="Copyright Brett Calcott and David Abrahams 2003. All rights reserved." />
|
||||
<title>Boost.Python Internals Boost</title>
|
||||
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="boost-python-internals">
|
||||
<h1 class="title">Boost Python Internals</h1>
|
||||
<h2 class="subtitle" id="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</h2>
|
||||
<table class="docinfo" frame="void" rules="none">
|
||||
<col class="docinfo-name" />
|
||||
<col class="docinfo-content" />
|
||||
<div class="document" id="boost-python-internals-logo">
|
||||
<h1 class="title"><a class="reference" href="index.html">Boost.Python</a> Internals <a class="reference" href="../../../index.htm"><img alt="Boost" src="../../../c++boost.gif" /></a></h1>
|
||||
<div class="section" id="a-conversation-between-brett-calcott-and-david-abrahams">
|
||||
<h1><a name="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</a></h1>
|
||||
<table class="field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr><th class="docinfo-name">Copyright:</th>
|
||||
<td>Copyright Brett Calcott and David Abrahams 2003. All
|
||||
rights reserved.</td></tr>
|
||||
<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_1_0.txt">license</a> for terms of use.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>In both of these cases, I'm quite capable of reading code - but the
|
||||
@@ -118,10 +118,11 @@ way from c++ to python and back again.</p>
|
||||
info in the LLNL progress reports and the messages they link to.
|
||||
Also,</p>
|
||||
<blockquote>
|
||||
<a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a>
|
||||
<a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-December/003115.html">http://mail.python.org/pipermail/c++-sig/2002-December/003115.html</a>
|
||||
<a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a>
|
||||
<a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-July/001755.html">http://mail.python.org/pipermail/c++-sig/2002-July/001755.html</a></blockquote>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a></p>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-December/003115.html">http://mail.python.org/pipermail/c++-sig/2002-December/003115.html</a></p>
|
||||
<p><a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a></p>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-July/001755.html">http://mail.python.org/pipermail/c++-sig/2002-July/001755.html</a></p>
|
||||
</blockquote>
|
||||
<p>from c++ to python:</p>
|
||||
<blockquote>
|
||||
<p>It depends on the type and the call policies in use or, for
|
||||
@@ -174,10 +175,11 @@ possible, then construct the converted object as a second step.</p>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/>
|
||||
<div class="footer">
|
||||
<a class="reference" href="internals.rst">View document source</a>.
|
||||
Generated on: 2003-07-31 17:58 UTC.
|
||||
Generated on: 2003-09-12 14:51 UTC.
|
||||
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
========================
|
||||
Boost Python Internals
|
||||
========================
|
||||
===================================
|
||||
Boost.Python_ Internals |(logo)|__
|
||||
===================================
|
||||
|
||||
.. |(logo)| image:: ../../../c++boost.gif
|
||||
:alt: Boost
|
||||
:class: boost-logo
|
||||
|
||||
__ ../../../index.htm
|
||||
|
||||
.. _`Boost.Python`: index.html
|
||||
|
||||
.. _license: ../../../LICENSE_1_0.txt
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
A conversation between Brett Calcott and David Abrahams
|
||||
-------------------------------------------------------
|
||||
|
||||
:copyright: Copyright Brett Calcott and David Abrahams 2003. All
|
||||
rights reserved.
|
||||
:copyright: Copyright David Abrahams and Brett Calcott 2003. See
|
||||
accompanying license_ for terms of use.
|
||||
|
||||
In both of these cases, I'm quite capable of reading code - but the
|
||||
thing I don't get from scanning the source is a sense of the
|
||||
@@ -107,8 +118,11 @@ Can you gesture in the general direction where these things are done?
|
||||
Also,
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
|
||||
|
||||
http://aspn.activestate.com/ASPN/Mail/Message/1280898
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
|
||||
|
||||
from c++ to python:
|
||||
|
||||
@@ -29,6 +29,36 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>11 Sept 2003</dt>
|
||||
|
||||
<dd>
|
||||
<ul>
|
||||
<li>Changed the response to multiple to-python converters being
|
||||
registered for the same type from a hard error into warning;
|
||||
Boost.Python now reports the offending type in the message.</li>
|
||||
|
||||
<li>Added builtin <code>std::wstring</code> conversions</li>
|
||||
|
||||
<li>Added <code>std::out_of_range</code> => Python
|
||||
<code>IndexError</code> exception conversion, thanks to <a href=
|
||||
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt>9 Sept 2003</dt>
|
||||
|
||||
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
|
||||
|
||||
<dt>constructors which take a range of characters, allowing strings
|
||||
containing nul (<code>'\0'</code>) characters.</dt>
|
||||
|
||||
<dt>8 Sept 2003</dt>
|
||||
|
||||
<dd>Added the ability to create methods from function objects (with an
|
||||
<code>operator()</code>); see the <a href=
|
||||
"v2/make_function.html#make_function-spec">make_function</a> docs for
|
||||
more info.</dd>
|
||||
|
||||
<dt>10 August 2003</dt>
|
||||
|
||||
<dd>Added the new <code>properties</code> unit tests contributed by <a
|
||||
@@ -78,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>
|
||||
|
||||
@@ -150,7 +180,8 @@ BOOST_PYTHON_MODULE(test)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
1 August 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
11 September 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<p>This is a list of available resources for support with Boost.Python
|
||||
problems and feature requests.</p>
|
||||
problems and feature requests. <b>Please try to resist emailing the
|
||||
Boost.Python developers directly for support.</b> Use the following
|
||||
resources instead; the developers are listening!</p>
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
@@ -41,9 +43,11 @@
|
||||
you Boost.Python.<br>
|
||||
</dt>
|
||||
|
||||
<dt><b><a href="http://www.python.org/sigs/c++-sig/">The Python
|
||||
<dt><b><a href=
|
||||
"http://www.boost.org/more/mailing_lists.htm#cplussig">The Python
|
||||
C++-sig</a></b> mailing list is a forum for discussing Python/C++
|
||||
interoperability, and Boost.Python in particular.<br>
|
||||
interoperability, and Boost.Python in particular. Post your
|
||||
Boost.Python questions here.<br>
|
||||
</dt>
|
||||
|
||||
<dt>The <b>Boost.Python <a href=
|
||||
@@ -51,18 +55,17 @@
|
||||
Pages</a></b> established by Mike Rovner as part of the <a href=
|
||||
"http://www.python.org/cgi-bin/moinmoin">PythonInfo Wiki</a> serves as
|
||||
a forum to gather peoples' experience and as a cookbook.<br>
|
||||
</dt>
|
||||
</dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
17 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
12 Sept, 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></p>
|
||||
Abrahams</a> 2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -37,6 +37,11 @@ with every boost distribution: <b>bjam</b>.</p>
|
||||
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>
|
||||
|
||||
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>
|
||||
@@ -62,6 +62,11 @@ with every boost distribution: [*bjam].
|
||||
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
|
||||
who had to use a different tool.
|
||||
]
|
||||
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
@@ -1005,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
|
||||
@@ -1053,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:
|
||||
|
||||
@@ -1693,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
|
||||
@@ -1713,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].
|
||||
@@ -1748,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:
|
||||
@@ -1758,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
|
||||
@@ -1775,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.
|
||||
@@ -1797,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(...)
|
||||
@@ -1849,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
|
||||
@@ -1869,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 *
|
||||
@@ -1877,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
|
||||
|
||||
@@ -1892,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):
|
||||
@@ -1941,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 */
|
||||
@@ -1957,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();
|
||||
@@ -1979,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
|
||||
|
||||
135
doc/v2/def_visitor.html
Normal file
135
doc/v2/def_visitor.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<meta name="generator" content="Microsoft FrontPage 5.0">
|
||||
<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/def_visitor.hpp></title>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html"><font size="7">Boost.Python</font></a></h1>
|
||||
|
||||
<h2 align="center">Header <boost/python/def_visitor.hpp></h2>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a>
|
||||
<dt><a href="#classes">Classes</a>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#def_visitor-spec">Class <code>def_visitor</code></a>
|
||||
<dd> <a href="#def_visitor-synopsis">Class <code>def_visitor</code>
|
||||
synopsis</a></dd>
|
||||
<dd> <a href="#def_visitor-requirements">Class <code>def_visitor</code>
|
||||
requirements</a></dd>
|
||||
</dl>
|
||||
<dt><a href="#examples">Example</a>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
|
||||
<p><code><boost/python/def_visitor.hpp></code> provides a generic visitation
|
||||
interface through which the <a href="class.html">class_</a> <b>def</b> member
|
||||
functionality can be extended non-intrusively to avoid cluttering the <a href="class.html">class_</a>
|
||||
interface. It declares the <code>def_visitor<T> </code>class template,
|
||||
which is parameterized on the derived type <tt>DerivedVisitor</tt>, which provides
|
||||
the actual <b>def</b> functionality through its <b>visit</b> member functions.
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="def_visitor-spec"></a>Class template <code>def_visitor<DerivedVisitor></code></h3>
|
||||
|
||||
|
||||
<p>The class def_visitor is a base class paramaterized by its derived class. The
|
||||
def_visitor class is a protocol class. Its derived class, DerivedVisitor, is
|
||||
expected to have a member function visit. The def_visitor class is never instantiated
|
||||
directly. Instead, an instance of its subclass, DerivedVisitor, is passed
|
||||
on as an argument to the <a href="class.html">class_</a> def member function.
|
||||
<h4>
|
||||
<a name="def_visitor-synopsis" id="def_visitor-synopsis"></a>Class <code>def_visitor </code>synopsis</h4>
|
||||
<pre>namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor>
|
||||
class def_visitor {};
|
||||
}</pre>
|
||||
<h3><a name="def_visitor-requirements"></a><code>def_visitor </code>requirements</h3>
|
||||
|
||||
|
||||
<p>The <span class="pre">client supplied class </span><span class="pre"></span><tt class="literal"><span class="pre">DerivedVisitor</span></tt>
|
||||
template parameter is expected to:
|
||||
<ul>
|
||||
<li>be privately derived from def_visitor</li>
|
||||
<li>grant friend access to class def_visitor_access</li>
|
||||
<li>define either or both visit member functions listed in the table below:</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<table border class="table">
|
||||
<tr>
|
||||
<td width="181" nowrap><b>Expression</b></td>
|
||||
<td width="85"><b>Return Type</b></td>
|
||||
<td width="330"><b>Requirements</b></td>
|
||||
<td width="259"><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td nowrap>visitor.visit(cls)</td>
|
||||
<td>void</td>
|
||||
<td>cls is an instance of a <a href="class.html">class_</a> being wrapped
|
||||
to Python. visitor is a def_visitor derived class.</td>
|
||||
<td>A call to cls.def(visitor) forwards to this member function.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td nowrap>visitor.visit(cls, name, options)</td>
|
||||
<td>void</td>
|
||||
<td>cls is a class_ instance, name is a C string. visitor is a def_visitor
|
||||
derived class. options is a context specific optional argument.</td>
|
||||
<td>A call to cls.def(name, visitor) or cls.def(name, visitor, options) forwards
|
||||
to this member function. </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
|
||||
<pre>class X {/*...*/};<br>
|
||||
class my_def_visitor : boost::python::def_visitor<my_def_visitor>
|
||||
{
|
||||
friend class def_visitor_access;
|
||||
|
||||
template <class classT>
|
||||
void visit(classT& c) const
|
||||
{
|
||||
c
|
||||
.def("foo", &my_def_visitor::foo)
|
||||
.def("bar", &my_def_visitor::bar)
|
||||
;
|
||||
}
|
||||
|
||||
static void foo(X& self);
|
||||
static void bar(X& self);
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(my_ext)
|
||||
{
|
||||
class_<X>("X")
|
||||
.def(my_def_visitor())
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->27 August, 2003<!--webbot bot="Timestamp" endspan i-checksum="34484" -->
|
||||
</p>
|
||||
|
||||
|
||||
<p><i>© Copyright Joel de Guzman 2003. All Rights Reserved.</i>
|
||||
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
|
||||
|
||||
@@ -66,9 +66,13 @@ template <class F, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies)
|
||||
|
||||
template <class F, class Policies, class Keywords>
|
||||
template <class F, class Policies, class KeywordsOrSignature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, Keywords const& keywords)
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
|
||||
|
||||
template <class F, class Policies, class Keywords, class Signature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
@@ -82,19 +86,41 @@ template <class F, class Policies, class Keywords>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which, when called
|
||||
from Python, converts its arguments to C++ and calls <code>f</code>. If
|
||||
<code>F</code> is a pointer-to-member-function type, the target object
|
||||
of the function call (<code>*this</code>) will be taken from the first
|
||||
Python argument, and subsequent Python arguments will be used as the
|
||||
arguments to <code>f</code>. If <code>policies</code> are supplied, it
|
||||
<code>F</code> is a pointer-to-member-function type, the target
|
||||
object of the function call (<code>*this</code>) will be taken
|
||||
from the first Python argument, and subsequent Python arguments
|
||||
will be used as the arguments
|
||||
to <code>f</code>. <ul>
|
||||
<li> If <code>policies</code> are supplied, it
|
||||
will be applied to the function as described <a href=
|
||||
"CallPolicies.html">here</a>. If <code>keywords</code> are
|
||||
"CallPolicies.html">here</a>.
|
||||
<li>If <code>keywords</code> are
|
||||
supplied, the keywords will be applied in order to the final
|
||||
arguments of the resulting function.</dt>
|
||||
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
|
||||
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
|
||||
you wish to override the types which will be passed to the
|
||||
wrapped function.
|
||||
</ul></dt>
|
||||
|
||||
<dt><b>Returns:</b> An instance of <a href=
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
|
||||
<dt><b>Caveats:</b> An argument of pointer type may
|
||||
be <code>0</code> if <code>None</code> is passed from Python.
|
||||
An argument type which is a constant reference may refer to a
|
||||
temporary which was created from the Python object for just the
|
||||
duration of the call to the wrapped function, for example
|
||||
a <code>std::vector</code> conjured up by the conversion process
|
||||
from a Python list. Use a non-<code>const</code> reference
|
||||
argument when a persistent lvalue is required.
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
<a name=
|
||||
"make_constructor-spec"></a>template <class T, class ArgList, class Generator>
|
||||
@@ -109,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>
|
||||
|
||||
@@ -196,6 +196,8 @@ namespace boost { namespace python { namespace self_ns {
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator+(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator~(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator!(self_t);
|
||||
|
||||
// value operations
|
||||
<a href=
|
||||
@@ -349,123 +351,123 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self == r</td>
|
||||
<td><code>self == r</code></td>
|
||||
|
||||
<td>__eq__</td>
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td>x == y</td>
|
||||
<td><code>x == y</code></td>
|
||||
|
||||
<td>x == y, y == x</td>
|
||||
<td><code>x == y, y == x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l == self</td>
|
||||
<td><code>l == self</code></td>
|
||||
|
||||
<td>__eq__</td>
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td>y == x</td>
|
||||
<td><code>y == x</code></td>
|
||||
|
||||
<td>y == x, x == y</td>
|
||||
<td><code>y == x, x == y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self != r</td>
|
||||
<td><code>self != r</code></td>
|
||||
|
||||
<td>__ne__</td>
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td>x != y</td>
|
||||
<td><code>x != y</code></td>
|
||||
|
||||
<td>x != y, y != x</td>
|
||||
<td><code>x != y, y != x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l != self</td>
|
||||
<td><code>l != self</code></td>
|
||||
|
||||
<td>__ne__</td>
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td>y != x</td>
|
||||
<td><code>y != x</code></td>
|
||||
|
||||
<td>y != x, x != y</td>
|
||||
<td><code>y != x, x != y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self < r</td>
|
||||
<td><code>self < r</code></td>
|
||||
|
||||
<td>__lt__</td>
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td>x < y</td>
|
||||
<td><code>x < y</code></td>
|
||||
|
||||
<td>x < y, y > x</td>
|
||||
<td><code>x < y, y > x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l < self</td>
|
||||
<td><code>l < self</code></td>
|
||||
|
||||
<td>__gt__</td>
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td>y < x</td>
|
||||
<td><code>y < x</code></td>
|
||||
|
||||
<td>y > x, x < y</td>
|
||||
<td><code>y > x, x < y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self > r</td>
|
||||
<td><code>self > r</code></td>
|
||||
|
||||
<td>__gt__</td>
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td>x > y</td>
|
||||
<td><code>x > y</code></td>
|
||||
|
||||
<td>x > y, y < x</td>
|
||||
<td><code>x > y, y < x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l > self</td>
|
||||
<td><code>l > self</code></td>
|
||||
|
||||
<td>__lt__</td>
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td>y > x</td>
|
||||
<td><code>y > x</code></td>
|
||||
|
||||
<td>y < x, x > y</td>
|
||||
<td><code>y < x, x > y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self <= r</td>
|
||||
<td><code>self <= r</code></td>
|
||||
|
||||
<td>__le__</td>
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td>x <= y</td>
|
||||
<td><code>x <= y</code></td>
|
||||
|
||||
<td>x <= y, y >= x</td>
|
||||
<td><code>x <= y, y >= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l <= self</td>
|
||||
<td><code>l <= self</code></td>
|
||||
|
||||
<td>__ge__</td>
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td>y <= x</td>
|
||||
<td><code>y <= x</code></td>
|
||||
|
||||
<td>y >= x, x <= y</td>
|
||||
<td><code>y >= x, x <= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self >= r</td>
|
||||
<td><code>self >= r</code></td>
|
||||
|
||||
<td>__ge__</td>
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td>x >= y</td>
|
||||
<td><code>x >= y</code></td>
|
||||
|
||||
<td>x >= y, y <= x</td>
|
||||
<td><code>x >= y, y <= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l >= self</td>
|
||||
<td><code>l >= self</code></td>
|
||||
|
||||
<td>__le__</td>
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td>y >= x</td>
|
||||
<td><code>y >= x</code></td>
|
||||
|
||||
<td>y <= x, x >= y</td>
|
||||
<td><code>y <= x, x >= y</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -487,183 +489,183 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self + r</td>
|
||||
<td><code>self + r</code></td>
|
||||
|
||||
<td>__add__</td>
|
||||
<td><code>__add__</code></td>
|
||||
|
||||
<td>x + y</td>
|
||||
<td><code>x + y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l + self</td>
|
||||
<td><code>l + self</code></td>
|
||||
|
||||
<td>__radd__</td>
|
||||
<td><code>__radd__</code></td>
|
||||
|
||||
<td>y + x</td>
|
||||
<td><code>y + x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self - r</td>
|
||||
<td><code>self - r</code></td>
|
||||
|
||||
<td>__sub__</td>
|
||||
<td><code>__sub__</code></td>
|
||||
|
||||
<td>x - y</td>
|
||||
<td><code>x - y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l - self</td>
|
||||
<td><code>l - self</code></td>
|
||||
|
||||
<td>__rsub__</td>
|
||||
<td><code>__rsub__</code></td>
|
||||
|
||||
<td>y - x</td>
|
||||
<td><code>y - x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self * r</td>
|
||||
<td><code>self * r</code></td>
|
||||
|
||||
<td>__mul__</td>
|
||||
<td><code>__mul__</code></td>
|
||||
|
||||
<td>x * y</td>
|
||||
<td><code>x * y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l * self</td>
|
||||
<td><code>l * self</code></td>
|
||||
|
||||
<td>__rmul__</td>
|
||||
<td><code>__rmul__</code></td>
|
||||
|
||||
<td>y * x</td>
|
||||
<td><code>y * x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self / r</td>
|
||||
<td><code>self / r</code></td>
|
||||
|
||||
<td>__div__</td>
|
||||
<td><code>__div__</code></td>
|
||||
|
||||
<td>x / y</td>
|
||||
<td><code>x / y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l / self</td>
|
||||
<td><code>l / self</code></td>
|
||||
|
||||
<td>__rdiv__</td>
|
||||
<td><code>__rdiv__</code></td>
|
||||
|
||||
<td>y / x</td>
|
||||
<td><code>y / x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self % r</td>
|
||||
<td><code>self % r</code></td>
|
||||
|
||||
<td>__mod__</td>
|
||||
<td><code>__mod__</code></td>
|
||||
|
||||
<td>x % y</td>
|
||||
<td><code>x % y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l % self</td>
|
||||
<td><code>l % self</code></td>
|
||||
|
||||
<td>__rmod__</td>
|
||||
<td><code>__rmod__</code></td>
|
||||
|
||||
<td>y % x</td>
|
||||
<td><code>y % x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self >> r</td>
|
||||
<td><code>self >> r</code></td>
|
||||
|
||||
<td>__rshift__</td>
|
||||
<td><code>__rshift__</code></td>
|
||||
|
||||
<td>x >> y</td>
|
||||
<td><code>x >> y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l >> self</td>
|
||||
<td><code>l >> self</code></td>
|
||||
|
||||
<td>__rrshift__</td>
|
||||
<td><code>__rrshift__</code></td>
|
||||
|
||||
<td>y >> x</td>
|
||||
<td><code>y >> x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self << r</td>
|
||||
<td><code>self << r</code></td>
|
||||
|
||||
<td>__lshift__</td>
|
||||
<td><code>__lshift__</code></td>
|
||||
|
||||
<td>x << y</td>
|
||||
<td><code>x << y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l << self</td>
|
||||
<td><code>l << self</code></td>
|
||||
|
||||
<td>__rlshift__</td>
|
||||
<td><code>__rlshift__</code></td>
|
||||
|
||||
<td>y << x</td>
|
||||
<td><code>y << x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self & r</td>
|
||||
<td><code>self & r</code></td>
|
||||
|
||||
<td>__and__</td>
|
||||
<td><code>__and__</code></td>
|
||||
|
||||
<td>x & y</td>
|
||||
<td><code>x & y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l & self</td>
|
||||
<td><code>l & self</code></td>
|
||||
|
||||
<td>__rand__</td>
|
||||
<td><code>__rand__</code></td>
|
||||
|
||||
<td>y & x</td>
|
||||
<td><code>y & x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self ^ r</td>
|
||||
<td><code>self ^ r</code></td>
|
||||
|
||||
<td>__xor__</td>
|
||||
<td><code>__xor__</code></td>
|
||||
|
||||
<td>x ^ y</td>
|
||||
<td><code>x ^ y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l ^ self</td>
|
||||
<td><code>l ^ self</code></td>
|
||||
|
||||
<td>__rxor__</td>
|
||||
<td><code>__rxor__</code></td>
|
||||
|
||||
<td>y ^ x</td>
|
||||
<td><code>y ^ x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self | r</td>
|
||||
<td><code>self | r</code></td>
|
||||
|
||||
<td>__or__</td>
|
||||
<td><code>__or__</code></td>
|
||||
|
||||
<td>x | y</td>
|
||||
<td><code>x | y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l | self</td>
|
||||
<td><code>l | self</code></td>
|
||||
|
||||
<td>__ror__</td>
|
||||
<td><code>__ror__</code></td>
|
||||
|
||||
<td>y | x</td>
|
||||
<td><code>y | x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>pow(self, r)</td>
|
||||
<td><code>pow(self, r)</code></td>
|
||||
|
||||
<td>__pow__</td>
|
||||
<td><code>__pow__</code></td>
|
||||
|
||||
<td>pow(x, y)</td>
|
||||
<td><code>pow(x, y)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>pow(l, self)</td>
|
||||
<td><code>pow(l, self)</code></td>
|
||||
|
||||
<td>__rpow__</td>
|
||||
<td><code>__rpow__</code></td>
|
||||
|
||||
<td>pow(y, x)</td>
|
||||
<td><code>pow(y, x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-unary-ops"></a>Class <code>self_t</code> unary
|
||||
<h4><a name="self_t-spec-value-unary-ops"></a>Class <code>self_t</code> unary
|
||||
operations</h4>
|
||||
|
||||
<table border="1" summary="self_t unary operations">
|
||||
@@ -676,27 +678,35 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>-self</td>
|
||||
<td><code>-self</code></td>
|
||||
|
||||
<td>__neg__</td>
|
||||
<td><code>__neg__</code></td>
|
||||
|
||||
<td>-x</td>
|
||||
<td><code>-x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>+self</td>
|
||||
<td><code>+self</code></td>
|
||||
|
||||
<td>__pos__</td>
|
||||
<td><code>__pos__</code></td>
|
||||
|
||||
<td>+x</td>
|
||||
<td><code>+x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>~self</td>
|
||||
<td><code>~self</code></td>
|
||||
|
||||
<td>__invert__</td>
|
||||
<td><code>__invert__</code></td>
|
||||
|
||||
<td>~x</td>
|
||||
<td><code>~x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>not self</code><br><i>or</i><br><code>!self</code></td>
|
||||
|
||||
<td><code>__nonzero__</code></td>
|
||||
|
||||
<td><code>!!x</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -713,44 +723,44 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>int_(self)</td>
|
||||
<td><code>int_(self)</code></td>
|
||||
|
||||
<td>__int__</td>
|
||||
<td><code>__int__</code></td>
|
||||
|
||||
<td>long(x)</td>
|
||||
<td><code>long(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>long_</td>
|
||||
<td><code>long_</code></td>
|
||||
|
||||
<td>__long__</td>
|
||||
<td><code>__long__</code></td>
|
||||
|
||||
<td>PyLong_FromLong(x)</td>
|
||||
<td><code>PyLong_FromLong(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>float_</td>
|
||||
<td><code>float_</code></td>
|
||||
|
||||
<td>__float__</td>
|
||||
<td><code>__float__</code></td>
|
||||
|
||||
<td>double(x)</td>
|
||||
<td><code>double(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>complex_</td>
|
||||
<td><code>complex_</code></td>
|
||||
|
||||
<td>__complex__</td>
|
||||
<td><code>__complex__</code></td>
|
||||
|
||||
<td>std::complex<double>(x)</td>
|
||||
<td><code>std::complex<double>(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>str</td>
|
||||
<td><code>str</code></td>
|
||||
|
||||
<td>__str__</td>
|
||||
<td><code>__str__</code></td>
|
||||
|
||||
<td><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</td>
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -876,7 +886,7 @@ BOOST_PYTHON_MODULE(demo)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
3 October, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -96,193 +96,158 @@
|
||||
|
||||
<h2><a name="high_level">High Level Components</a></h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"module.html#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
||||
<dt><a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a></dt>
|
||||
<dt><a href=
|
||||
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"module.html#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="object_wrappers">Object Wrappers</a></h2>
|
||||
|
||||
@@ -371,7 +336,7 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="str.html">tuple.hpp</a></dt>
|
||||
<dt><a href="tuple.html">tuple.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
@@ -392,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>
|
||||
@@ -67,8 +67,10 @@
|
||||
<p>Exposes the <a href=
|
||||
"http://www.python.org/dev/doc/devel/lib/string-methods.html">string
|
||||
methods</a> of Python's built-in <code>str</code> type. The
|
||||
semantics of the constructors and member functions defined below
|
||||
can be fully understood by reading the <a href=
|
||||
semantics of the constructors and member functions defined below,
|
||||
except for the two-argument constructors which construct str
|
||||
objects from a range of characters, can be fully understood by
|
||||
reading the <a href=
|
||||
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
|
||||
definition. Since <code>str</code> is publicly derived from
|
||||
<code><a href="object.html#object-spec">object</a></code>, the
|
||||
@@ -85,7 +87,10 @@ namespace boost { namespace python
|
||||
public:
|
||||
str(); // new str
|
||||
|
||||
str(const char* s); // new str
|
||||
str(char const* s); // new str
|
||||
|
||||
str(char const* start, char const* finish); // new str
|
||||
str(char const* start, std::size_t length); // new str
|
||||
|
||||
template <class T>
|
||||
explicit str(T const& other);
|
||||
|
||||
@@ -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,5 +1,8 @@
|
||||
# Specify our location in the boost project hierarchy
|
||||
subproject libs/python/example ;
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
# Declares the following targets:
|
||||
#
|
||||
@@ -19,18 +22,17 @@ subproject libs/python/example ;
|
||||
#
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include python.jam ;
|
||||
import python ;
|
||||
|
||||
# ----- getting_started1 -------
|
||||
|
||||
# Declare a Python extension called getting_started1
|
||||
extension getting_started1
|
||||
: # sources
|
||||
getting_started1.cpp
|
||||
: # sources
|
||||
getting_started1.cpp
|
||||
|
||||
# dependencies
|
||||
<dll>../build/boost_python
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
@@ -49,8 +51,8 @@ extension getting_started2
|
||||
: # sources
|
||||
getting_started2.cpp
|
||||
|
||||
# dependencies
|
||||
<dll>../build/boost_python
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
|
||||
7
example/Jamrules
Executable file
7
example/Jamrules
Executable file
@@ -0,0 +1,7 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# Edit this path to point at the root directory of your Boost
|
||||
# installation. Absolute paths work, too.
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
6
example/boost-build.jam
Executable file
6
example/boost-build.jam
Executable file
@@ -0,0 +1,6 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# Edit this path to point at the tools/build/v1 subdirectory of your
|
||||
# Boost installation. Absolute paths work, too.
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
18
example/test_getting_started1.py
Normal file
18
example/test_getting_started1.py
Normal file
@@ -0,0 +1,18 @@
|
||||
r'''>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started1
|
||||
return doctest.testmod(test_getting_started1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
31
example/test_getting_started2.py
Normal file
31
example/test_getting_started2.py
Normal file
@@ -0,0 +1,31 @@
|
||||
r'''>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started2
|
||||
return doctest.testmod(test_getting_started2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
subproject libs/python/example/tutorial ;
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include python.jam ;
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
|
||||
@@ -48,9 +48,11 @@
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/python/overloads.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/pure_virtual.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/return_arg.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
|
||||
@@ -26,51 +26,25 @@ struct arg_from_python<PyObject*>
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
arg_from_python(PyObject*) {}
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject* operator()(PyObject* source) const { return source; }
|
||||
PyObject* operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct arg_from_python<PyObject* const&>
|
||||
{
|
||||
typedef PyObject* const& result_type;
|
||||
arg_from_python(PyObject*) {}
|
||||
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject*const& operator()(PyObject*const& source) const { return source; }
|
||||
PyObject*const& operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Meta-iterators for use with caller<>
|
||||
//
|
||||
|
||||
// temporary hack
|
||||
template <class T> struct nullary : T
|
||||
{
|
||||
nullary(PyObject* x) : T(x), m_p(x) {}
|
||||
typename T::result_type operator()() { return this->T::operator()(m_p); }
|
||||
PyObject* m_p;
|
||||
};
|
||||
|
||||
// An MPL metafunction class which returns arg_from_python<ArgType>
|
||||
struct gen_arg_from_python
|
||||
{
|
||||
template <class ArgType> struct apply
|
||||
{
|
||||
typedef nullary<arg_from_python<ArgType> > type;
|
||||
};
|
||||
};
|
||||
|
||||
// An MPL iterator over an endless sequence of gen_arg_from_python
|
||||
struct args_from_python
|
||||
{
|
||||
typedef gen_arg_from_python type;
|
||||
typedef args_from_python next;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
|
||||
@@ -48,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
|
||||
@@ -128,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_<
|
||||
@@ -136,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
|
||||
@@ -338,81 +344,53 @@ 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
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(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
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
base::add_property(name, this->make_getter(fget), this->make_setter(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get>
|
||||
self& add_static_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
);
|
||||
|
||||
base::add_static_property(name, object(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_static_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
base::add_static_property(name, object(fget), object(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -437,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);
|
||||
@@ -444,34 +428,86 @@ 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_getter(F f)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// }
|
||||
|
||||
template <class D, class B>
|
||||
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;
|
||||
@@ -481,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
|
||||
@@ -501,21 +538,27 @@ class class_ : public objects::class_base
|
||||
)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, helper.policies(), helper.keywords())
|
||||
, helper.doc());
|
||||
*this
|
||||
, name
|
||||
, make_function(
|
||||
fn
|
||||
, helper.policies()
|
||||
, helper.keywords()
|
||||
, detail::get_signature(fn, (T*)0)
|
||||
)
|
||||
, helper.doc()
|
||||
);
|
||||
|
||||
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
|
||||
@@ -536,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
|
||||
@@ -543,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
|
||||
@@ -572,6 +617,7 @@ class class_ : public objects::class_base
|
||||
);
|
||||
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ struct pointer_cref_arg_from_python
|
||||
typedef T result_type;
|
||||
|
||||
pointer_cref_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
bool convertible() const;
|
||||
|
||||
private: // storage for a U*
|
||||
@@ -74,7 +74,7 @@ struct pointer_arg_from_python : arg_lvalue_from_python_base
|
||||
typedef T result_type;
|
||||
|
||||
pointer_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// Used when T == U& and (T != V const& or T == W volatile&)
|
||||
@@ -84,7 +84,7 @@ struct reference_arg_from_python : arg_lvalue_from_python_base
|
||||
typedef T result_type;
|
||||
|
||||
reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// ===================
|
||||
@@ -114,10 +114,11 @@ struct arg_rvalue_from_python
|
||||
# if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
|
||||
typename arg_rvalue_from_python<T>::
|
||||
# endif
|
||||
result_type operator()(PyObject*);
|
||||
result_type operator()();
|
||||
|
||||
private:
|
||||
rvalue_from_python_data<result_type> m_data;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
@@ -132,9 +133,10 @@ struct back_reference_arg_from_python
|
||||
typedef T result_type;
|
||||
|
||||
back_reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*);
|
||||
T operator()();
|
||||
private:
|
||||
typedef boost::python::arg_from_python<typename T::type> base;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
@@ -259,9 +261,9 @@ inline bool pointer_cref_arg_from_python<T>::convertible() const
|
||||
return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
|
||||
}
|
||||
template <class T>
|
||||
inline T pointer_cref_arg_from_python<T>::operator()(PyObject* p) const
|
||||
inline T pointer_cref_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (p == Py_None) // None ==> 0
|
||||
return (*(void**)m_result.bytes == Py_None) // None ==> 0
|
||||
? detail::null_ptr_reference((T(*)())0)
|
||||
// Otherwise, return a U*const& to the m_result storage.
|
||||
: python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
|
||||
@@ -277,9 +279,9 @@ inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_arg_from_python<T>::operator()(PyObject* p) const
|
||||
inline T pointer_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (p == Py_None) ? 0 : T(result());
|
||||
return (result() == Py_None) ? 0 : T(result());
|
||||
}
|
||||
|
||||
// reference_arg_from_python
|
||||
@@ -291,7 +293,7 @@ inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_arg_from_python<T>::operator()(PyObject*) const
|
||||
inline T reference_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(result(), (T(*)())0);
|
||||
}
|
||||
@@ -302,6 +304,7 @@ inline T reference_arg_from_python<T>::operator()(PyObject*) const
|
||||
template <class T>
|
||||
inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
|
||||
: m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
|
||||
, m_source(obj)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -313,10 +316,10 @@ inline bool arg_rvalue_from_python<T>::convertible() const
|
||||
|
||||
template <class T>
|
||||
inline typename arg_rvalue_from_python<T>::result_type
|
||||
arg_rvalue_from_python<T>::operator()(PyObject* p)
|
||||
arg_rvalue_from_python<T>::operator()()
|
||||
{
|
||||
if (m_data.stage1.construct != 0)
|
||||
m_data.stage1.construct(p, &m_data.stage1);
|
||||
m_data.stage1.construct(m_source, &m_data.stage1);
|
||||
|
||||
return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
@@ -325,15 +328,15 @@ arg_rvalue_from_python<T>::operator()(PyObject* p)
|
||||
//
|
||||
template <class T>
|
||||
back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
|
||||
: base(x)
|
||||
: base(x), m_source(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
back_reference_arg_from_python<T>::operator()(PyObject* x)
|
||||
back_reference_arg_from_python<T>::operator()()
|
||||
{
|
||||
return T(x, base::operator()(x));
|
||||
return T(m_source, base::operator()());
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -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>
|
||||
@@ -82,16 +83,16 @@ namespace detail
|
||||
|
||||
// Specialize converters for signed and unsigned T to Python Int
|
||||
# define BOOST_PYTHON_TO_INT(T) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
|
||||
unsigned T \
|
||||
, static_cast<unsigned long>(x) > static_cast<unsigned long>( \
|
||||
std::numeric_limits<long>::max()) \
|
||||
? PyLong_FromUnsignedLong(x) \
|
||||
: PyInt_FromLong(x))
|
||||
? ::PyLong_FromUnsignedLong(x) \
|
||||
: ::PyInt_FromLong(x))
|
||||
|
||||
// Bool is not signed.
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x))
|
||||
|
||||
// note: handles signed char and unsigned char, but not char (see below)
|
||||
BOOST_PYTHON_TO_INT(char)
|
||||
@@ -103,23 +104,31 @@ BOOST_PYTHON_TO_INT(long)
|
||||
// using Python's macro instead of Boost's - we don't seem to get the
|
||||
// config right all the time.
|
||||
# ifdef HAVE_LONG_LONG
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, PyLong_FromUnsignedLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x))
|
||||
# endif
|
||||
|
||||
# undef BOOST_TO_PYTHON_INT
|
||||
|
||||
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.c_str(),x.size()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
|
||||
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(),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))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
|
||||
# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_INT
|
||||
|
||||
namespace converter
|
||||
{
|
||||
|
||||
|
||||
18
include/boost/python/converter/context_result_converter.hpp
Executable file
18
include/boost/python/converter/context_result_converter.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
# define CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// A ResultConverter base class used to indicate that this result
|
||||
// converter should be constructed with the original Python argument
|
||||
// list.
|
||||
struct context_result_converter {};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
@@ -27,7 +27,7 @@ struct object_manager_value_arg_from_python
|
||||
|
||||
object_manager_value_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
@@ -48,7 +48,7 @@ struct object_manager_ref_arg_from_python
|
||||
|
||||
object_manager_ref_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
Ref operator()(PyObject*) const;
|
||||
Ref operator()() const;
|
||||
~object_manager_ref_arg_from_python();
|
||||
private:
|
||||
typename python::detail::referent_storage<Ref>::type m_result;
|
||||
@@ -71,9 +71,9 @@ inline bool object_manager_value_arg_from_python<T>::convertible() const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T object_manager_value_arg_from_python<T>::operator()(PyObject* x) const
|
||||
inline T object_manager_value_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return T(python::detail::borrowed_reference(x));
|
||||
return T(python::detail::borrowed_reference(m_source));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
@@ -111,7 +111,7 @@ inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()(PyObject*) const
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
this->m_result.bytes, (Ref(*)())0);
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
//
|
||||
// arg_from_python converters for Python type wrappers, to be used as
|
||||
// base classes for specializations.
|
||||
//
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
struct pytype_arg_from_python
|
||||
{
|
||||
pytype_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
private:
|
||||
PyObject* m_src;
|
||||
};
|
||||
|
||||
// rvalue converter base
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_value_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper result_type;
|
||||
|
||||
pytype_wrapper_value_arg_from_python(PyObject*);
|
||||
Wrapper operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
// Special case for Wrapper& - must store an lvalue internally. This
|
||||
// OK because the entire state of the object is actually in the Python
|
||||
// object.
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_ref_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper& result_type;
|
||||
|
||||
pytype_wrapper_ref_arg_from_python(PyObject*);
|
||||
Wrapper& operator()(PyObject*) const;
|
||||
private:
|
||||
mutable Wrapper m_result;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline pytype_arg_from_python<python_type>::pytype_arg_from_python(PyObject* x)
|
||||
: m_src(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline bool pytype_arg_from_python<python_type>::convertible() const
|
||||
{
|
||||
return PyObject_IsInstance(m_src, (PyObject*)python_type);
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_value_arg_from_python<Wrapper,python_type>::pytype_wrapper_value_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper pytype_wrapper_value_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return Wrapper(python::detail::borrowed_reference(x));
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::pytype_wrapper_ref_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
, m_result(python::detail::borrowed_reference(p))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper& pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/return_by_value.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/is_member_pointer.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
# endif
|
||||
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
@@ -43,97 +45,57 @@ namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Raw Getter and Setter function generators. These class templates
|
||||
// generate static functions which can be bound together with
|
||||
// policies and wrapped to generate the python callable objects
|
||||
// mentioned above.
|
||||
//
|
||||
|
||||
//
|
||||
// Generates get and set functions for access through
|
||||
// pointers-to-data-members
|
||||
//
|
||||
template <class Data, class Class, class Policies>
|
||||
// A small function object which handles the getting and setting of
|
||||
// data members.
|
||||
template <class Data, class Class>
|
||||
struct member
|
||||
{
|
||||
static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( (c0(PyTuple_GET_ITEM(args_, 0)))->*pm );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
arg_from_python<Class&> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c1(PyTuple_GET_ITEM(args_, 1));
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
if (!c1.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
(c0(PyTuple_GET_ITEM(args_, 0))).*pm = c1(PyTuple_GET_ITEM(args_, 1));
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
public:
|
||||
member(Data Class::*which) : m_which(which) {}
|
||||
|
||||
Data& operator()(Class& c) const
|
||||
{
|
||||
return c.*m_which;
|
||||
}
|
||||
|
||||
void operator()(Class& c, data_cref d) const
|
||||
{
|
||||
c.*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data Class::*m_which;
|
||||
};
|
||||
|
||||
//
|
||||
// Generates get and set functions for access through ordinary
|
||||
// pointers. These are generally used to wrap static data members,
|
||||
// but can also be used to expose namespace-scope data as class
|
||||
// attributes.
|
||||
//
|
||||
template <class Data, class Policies>
|
||||
// A small function object which handles the getting and setting of
|
||||
// non-member objects.
|
||||
template <class Data>
|
||||
struct datum
|
||||
{
|
||||
static PyObject* get(Data *p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( *p );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data* p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
*p = c0(PyTuple_GET_ITEM(args_, 0));
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
public:
|
||||
datum(Data *which) : m_which(which) {}
|
||||
|
||||
Data& operator()() const
|
||||
{
|
||||
return *m_which;
|
||||
}
|
||||
};
|
||||
|
||||
void operator()(data_cref d) const
|
||||
{
|
||||
*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data *m_which;
|
||||
};
|
||||
|
||||
//
|
||||
// Helper metafunction for determining the default CallPolicy to use
|
||||
// for attribute access. If T is a [reference to a] class type X
|
||||
@@ -208,13 +170,8 @@ namespace detail
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::get, d, _1, _2
|
||||
, policies)
|
||||
, mpl::vector1<D>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::datum<D>(d), policies, mpl::vector1<D&>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -230,14 +187,16 @@ namespace detail
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::get, pm, _1, _2
|
||||
, policies)
|
||||
, mpl::vector2<D, C const*>()
|
||||
)
|
||||
);
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
typedef typename remove_cv<C>::type Class;
|
||||
#else
|
||||
typedef C Class;
|
||||
#endif
|
||||
return python::make_function(
|
||||
detail::member<D,Class>(pm)
|
||||
, policies
|
||||
, mpl::vector2<D&,Class&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle pointers-to-members without policies
|
||||
@@ -268,13 +227,8 @@ namespace detail
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::set, p, _1, _2
|
||||
, policies)
|
||||
, mpl::vector2<void, D const&>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -282,13 +236,10 @@ namespace detail
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, mpl::vector3<void, C*, D const&>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::member<D,C>(pm)
|
||||
, policies
|
||||
, mpl::vector3<void, C&, D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,19 +29,23 @@ struct default_result_converter;
|
||||
|
||||
struct default_call_policies
|
||||
{
|
||||
// Nothing to do
|
||||
static bool precall(PyObject*)
|
||||
// Ownership of this argument tuple will ultimately be adopted by
|
||||
// the caller.
|
||||
template <class ArgumentPackage>
|
||||
static bool precall(ArgumentPackage const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass the result through
|
||||
static PyObject* postcall(PyObject*, PyObject* result)
|
||||
template <class ArgumentPackage>
|
||||
static PyObject* postcall(ArgumentPackage const&, PyObject* result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef default_result_converter result_converter;
|
||||
typedef PyObject* argument_package;
|
||||
};
|
||||
|
||||
struct default_result_converter
|
||||
|
||||
@@ -9,70 +9,100 @@
|
||||
# ifndef CALLER_DWA20021121_HPP
|
||||
# define CALLER_DWA20021121_HPP
|
||||
|
||||
# include <boost/compressed_pair.hpp>
|
||||
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/at.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/detail/invoke.hpp>
|
||||
# include <boost/python/detail/signature.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/python/converter/context_result_converter.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/repeat.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/dec.hpp>
|
||||
# include <boost/preprocessor/if.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/detail/invoke.hpp>
|
||||
# include <boost/python/detail/signature.hpp>
|
||||
# include <boost/compressed_pair.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/at.hpp>
|
||||
# include <boost/mpl/int.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <int N>
|
||||
inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
|
||||
{
|
||||
return PyTuple_GET_ITEM(args_,N);
|
||||
}
|
||||
|
||||
inline unsigned arity(PyObject* const& args_)
|
||||
{
|
||||
return PyTuple_GET_SIZE(args_);
|
||||
}
|
||||
|
||||
// This "result converter" is really just used as
|
||||
// a dispatch tag to invoke(...), selecting the appropriate
|
||||
// implementation
|
||||
typedef int void_result_to_python;
|
||||
|
||||
// A metafunction taking an iterator FunctionIter to a metafunction
|
||||
// class and an iterator ArgIter to an argument, which applies the
|
||||
// result of dereferencing FunctionIter to the result of dereferencing
|
||||
// ArgIter
|
||||
template <class FunctionIter, class ArgIter>
|
||||
struct apply_iter1
|
||||
: mpl::apply1<typename FunctionIter::type, typename ArgIter::type> {};
|
||||
|
||||
// Given a model of CallPolicies and a C++ result type, this
|
||||
// metafunction selects the appropriate converter to use for
|
||||
// converting the result to python.
|
||||
template <class Policies, class Result>
|
||||
struct select_result_converter
|
||||
: mpl::if_<
|
||||
: mpl::apply_if<
|
||||
is_same<Result,void>
|
||||
, void_result_to_python
|
||||
, typename mpl::apply1<typename Policies::result_converter,Result>::type*
|
||||
, mpl::identity<void_result_to_python>
|
||||
, mpl::apply1<typename Policies::result_converter,Result>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
template <class ArgPackage, class ResultConverter>
|
||||
inline ResultConverter create_result_converter(
|
||||
ArgPackage const& args_
|
||||
, ResultConverter*
|
||||
, converter::context_result_converter*
|
||||
)
|
||||
{
|
||||
return ResultConverter(args_);
|
||||
}
|
||||
|
||||
template <class ArgPackage, class ResultConverter>
|
||||
inline ResultConverter create_result_converter(
|
||||
ArgPackage const& args_
|
||||
, ResultConverter*
|
||||
, ...
|
||||
)
|
||||
{
|
||||
return ResultConverter();
|
||||
}
|
||||
|
||||
template <unsigned> struct caller_arity;
|
||||
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
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;
|
||||
|
||||
# define BOOST_PYTHON_ARG_CONVERTER(n) \
|
||||
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
|
||||
BOOST_PYTHON_NEXT(ConverterGenerators, conv_iter,n) \
|
||||
typedef typename apply_iter1<conv_iter##n,arg_iter##n>::type c_t##n; \
|
||||
c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \
|
||||
if (!c##n.convertible()) \
|
||||
# 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;
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
@@ -84,11 +114,11 @@ struct caller;
|
||||
|
||||
// A metafunction returning the base class used for caller<class F,
|
||||
// class ConverterGenerators, class CallPolicies, class Sig>.
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
struct caller_base_select
|
||||
{
|
||||
enum { arity = mpl::size<Sig>::value - 1 };
|
||||
typedef typename caller_arity<arity>::template impl<F,ConverterGenerators,CallPolicies,Sig> type;
|
||||
typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type;
|
||||
};
|
||||
|
||||
// A function object type which wraps C++ objects as Python callable
|
||||
@@ -101,11 +131,6 @@ struct caller_base_select
|
||||
// actually be any data for which an appropriate invoke_tag() can
|
||||
// be generated. invoke(...) takes care of the actual invocation syntax.
|
||||
//
|
||||
// ConverterGenerators -
|
||||
// An MPL iterator type over a sequence of metafunction classes
|
||||
// that can be applied to element 1...N of Sig to produce
|
||||
// argument from_python converters for the arguments
|
||||
//
|
||||
// CallPolicies -
|
||||
// The precall, postcall, and what kind of resultconverter to
|
||||
// generate for mpl::front<Sig>::type
|
||||
@@ -114,12 +139,12 @@ struct caller_base_select
|
||||
// The `intended signature' of the function. An MPL sequence
|
||||
// beginning with a result type and continuing with a list of
|
||||
// argument types.
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
struct caller
|
||||
: caller_base_select<F,ConverterGenerators,CallPolicies,Sig>::type
|
||||
: caller_base_select<F,CallPolicies,Sig>::type
|
||||
{
|
||||
typedef typename caller_base_select<
|
||||
F,ConverterGenerators,CallPolicies,Sig
|
||||
F,CallPolicies,Sig
|
||||
>::type base;
|
||||
|
||||
typedef PyObject* result_type;
|
||||
@@ -139,7 +164,7 @@ struct caller
|
||||
template <>
|
||||
struct caller_arity<N>
|
||||
{
|
||||
template <class F, class ConverterGenerators, class Policies, class Sig>
|
||||
template <class F, class Policies, class Sig>
|
||||
struct impl
|
||||
{
|
||||
impl(F f, Policies p) : m_data(f,p) {}
|
||||
@@ -152,6 +177,10 @@ struct caller_arity<N>
|
||||
typedef typename mpl::begin<Sig>::type first;
|
||||
typedef typename first::type result_t;
|
||||
typedef typename select_result_converter<Policies, result_t>::type result_converter;
|
||||
typedef typename Policies::argument_package argument_package;
|
||||
|
||||
argument_package inner_args(args_);
|
||||
|
||||
# if N
|
||||
# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
|
||||
# define BOOST_PP_LOCAL_LIMITS (0, N-1)
|
||||
@@ -159,15 +188,17 @@ struct caller_arity<N>
|
||||
# endif
|
||||
// all converters have been checked. Now we can do the
|
||||
// precall part of the policy
|
||||
if (!m_data.second().precall(args_))
|
||||
if (!m_data.second().precall(inner_args))
|
||||
return 0;
|
||||
|
||||
typedef typename detail::invoke_tag<F>::type tag;
|
||||
|
||||
PyObject* result = detail::invoke(
|
||||
tag(), result_converter(), m_data.first() BOOST_PP_ENUM_TRAILING_PARAMS(N, c));
|
||||
detail::invoke_tag<result_t,F>()
|
||||
, create_result_converter(args_, (result_converter*)0, (result_converter*)0)
|
||||
, m_data.first()
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(N, c)
|
||||
);
|
||||
|
||||
return m_data.second().postcall(args_, result);
|
||||
return m_data.second().postcall(inner_args, result);
|
||||
}
|
||||
|
||||
static unsigned min_arity() { return N; }
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -37,8 +37,13 @@ namespace objects
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class F> struct member_function_cast;
|
||||
|
||||
// Called as::
|
||||
//
|
||||
// name_space_def(ns, "func", func, kw, policies, docstring, &ns)
|
||||
//
|
||||
// Dispatch to properly add f to namespace ns.
|
||||
//
|
||||
// @group define_stub_function helpers {
|
||||
template <class Func, class CallPolicies, class NameSpaceT>
|
||||
static void name_space_def(
|
||||
NameSpaceT& name_space
|
||||
@@ -55,10 +60,9 @@ namespace detail
|
||||
objects::add_to_namespace(
|
||||
name_space, name,
|
||||
detail::make_keyword_range_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
member_function_cast<wrapped_type,Func>::stage1(f).stage2((wrapped_type*)0).stage3(f)
|
||||
, policies, kw)
|
||||
, doc);
|
||||
f, policies, kw, get_signature(f, (wrapped_type*)0))
|
||||
, doc
|
||||
);
|
||||
}
|
||||
|
||||
template <class Func, class CallPolicies>
|
||||
@@ -80,7 +84,7 @@ namespace detail
|
||||
, doc);
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
// For backward compatibility -- is this obsolete?
|
||||
template <class Func, class CallPolicies, class NameSpaceT>
|
||||
static void name_space_def(
|
||||
NameSpaceT& name_space
|
||||
@@ -94,10 +98,10 @@ namespace detail
|
||||
{
|
||||
name_space.def(name, f, policies, doc);
|
||||
}
|
||||
// }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This Boost PP code generates expansions for
|
||||
|
||||
// Expansions of ::
|
||||
//
|
||||
// template <typename OverloadsT, typename NameSpaceT>
|
||||
// inline void
|
||||
@@ -107,7 +111,7 @@ namespace detail
|
||||
// name_space.def(name, &OverloadsT::func_N);
|
||||
// }
|
||||
//
|
||||
// where N runs from 0 to BOOST_PYTHON_MAX_ARITY
|
||||
// where N runs from 0 to BOOST_PYTHON_MAX_ARITY.
|
||||
//
|
||||
// The set of overloaded functions (define_stub_function) expects:
|
||||
//
|
||||
@@ -118,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 {};
|
||||
|
||||
@@ -126,129 +130,137 @@ namespace detail
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/defaults_def.hpp>))
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
// }
|
||||
|
||||
// This helper template struct does the actual recursive
|
||||
// definition. There's a generic version
|
||||
// define_with_defaults_helper<N> and a terminal case
|
||||
// define_with_defaults_helper<0>. The struct and its
|
||||
// specialization has a sole static member function def that
|
||||
// expects:
|
||||
//
|
||||
// 1. char const* name: function name that will be
|
||||
// visible to python
|
||||
//
|
||||
// 2. OverloadsT: a function overloads struct
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 3. NameSpaceT& name_space: a python::class_ or
|
||||
// python::module instance
|
||||
//
|
||||
// 4. char const* name: doc string
|
||||
//
|
||||
// The def static member function calls a corresponding
|
||||
// define_stub_function<N>. The general case recursively calls
|
||||
// define_with_defaults_helper<N-1>::def until it reaches the
|
||||
// terminal case case define_with_defaults_helper<0>.
|
||||
template <int N>
|
||||
struct define_with_defaults_helper {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// define_with_defaults_helper<N>
|
||||
//
|
||||
// This helper template struct does the actual recursive definition.
|
||||
// There's a generic version define_with_defaults_helper<N> and a
|
||||
// terminal case define_with_defaults_helper<0>. The struct and its
|
||||
// specialization has a sole static member function def that expects:
|
||||
//
|
||||
// 1. char const* name: function name that will be visible to python
|
||||
// 2. OverloadsT: a function overloads struct (see defaults_gen.hpp)
|
||||
// 3. NameSpaceT& name_space: a python::class_ or python::module instance
|
||||
// 4. char const* name: doc string
|
||||
//
|
||||
// The def static member function calls a corresponding
|
||||
// define_stub_function<N>. The general case recursively calls
|
||||
// define_with_defaults_helper<N-1>::def until it reaches the
|
||||
// terminal case case define_with_defaults_helper<0>.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <int N>
|
||||
struct define_with_defaults_helper {
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the NTH stub function of stubs
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
|
||||
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the NTH stub function of stubs
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
|
||||
|
||||
if (kw.second > kw.first)
|
||||
--kw.second;
|
||||
|
||||
// call the next define_with_defaults_helper
|
||||
define_with_defaults_helper<N-1>::def(name, stubs, kw, policies, name_space, doc);
|
||||
}
|
||||
};
|
||||
if (kw.second > kw.first)
|
||||
--kw.second;
|
||||
|
||||
///////////////////////////////////////
|
||||
template <>
|
||||
struct define_with_defaults_helper<0> {
|
||||
// call the next define_with_defaults_helper
|
||||
define_with_defaults_helper<N-1>::def(name, stubs, kw, policies, name_space, doc);
|
||||
}
|
||||
};
|
||||
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range const& kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the Oth stub function of stubs
|
||||
define_stub_function<0>::define(name, stubs, kw, policies, name_space, doc);
|
||||
// return
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct define_with_defaults_helper<0> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// define_with_defaults
|
||||
//
|
||||
// 1. char const* name: function name that will be visible to python
|
||||
// 2. OverloadsT: a function overloads struct (see defaults_gen.hpp)
|
||||
// 3. CallPolicies& policies: Call policies
|
||||
// 4. NameSpaceT& name_space: a python::class_ or python::module instance
|
||||
// 5. SigT sig: Function signature typelist (see defaults_gen.hpp)
|
||||
// 6. char const* name: doc string
|
||||
//
|
||||
// This is the main entry point. This function recursively defines all
|
||||
// stub functions of StubT (see defaults_gen.hpp) in NameSpaceT name_space which
|
||||
// can be either a python::class_ or a python::module. The sig argument
|
||||
// is a typelist that specifies the return type, the class (for member
|
||||
// functions, and the arguments. Here are some SigT examples:
|
||||
//
|
||||
// int foo(int) mpl::list<int, int>
|
||||
// void bar(int, int) mpl::list<void, int, int>
|
||||
// void C::foo(int) mpl::list<void, C, int>
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <class OverloadsT, class NameSpaceT, class SigT>
|
||||
inline void
|
||||
define_with_defaults(
|
||||
char const* name,
|
||||
OverloadsT const& overloads,
|
||||
NameSpaceT& name_space,
|
||||
SigT const&)
|
||||
{
|
||||
typedef typename mpl::front<SigT>::type return_type;
|
||||
typedef typename OverloadsT::void_return_type void_return_type;
|
||||
typedef typename OverloadsT::non_void_return_type non_void_return_type;
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range const& kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the Oth stub function of stubs
|
||||
define_stub_function<0>::define(name, stubs, kw, policies, name_space, doc);
|
||||
// return
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
boost::is_same<void, return_type>::value
|
||||
, void_return_type
|
||||
, non_void_return_type
|
||||
>::type stubs_type;
|
||||
// define_with_defaults
|
||||
//
|
||||
// 1. char const* name: function name that will be
|
||||
// visible to python
|
||||
//
|
||||
// 2. OverloadsT: a function overloads struct
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 3. CallPolicies& policies: Call policies
|
||||
// 4. NameSpaceT& name_space: a python::class_ or
|
||||
// python::module instance
|
||||
//
|
||||
// 5. SigT sig: Function signature typelist
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 6. char const* name: doc string
|
||||
//
|
||||
// This is the main entry point. This function recursively
|
||||
// defines all stub functions of StubT (see defaults_gen.hpp) in
|
||||
// NameSpaceT name_space which can be either a python::class_ or
|
||||
// a python::module. The sig argument is a typelist that
|
||||
// specifies the return type, the class (for member functions,
|
||||
// and the arguments. Here are some SigT examples:
|
||||
//
|
||||
// int foo(int) mpl::vector<int, int>
|
||||
// void bar(int, int) mpl::vector<void, int, int>
|
||||
// void C::foo(int) mpl::vector<void, C, int>
|
||||
//
|
||||
template <class OverloadsT, class NameSpaceT, class SigT>
|
||||
inline void
|
||||
define_with_defaults(
|
||||
char const* name,
|
||||
OverloadsT const& overloads,
|
||||
NameSpaceT& name_space,
|
||||
SigT const&)
|
||||
{
|
||||
typedef typename mpl::front<SigT>::type return_type;
|
||||
typedef typename OverloadsT::void_return_type void_return_type;
|
||||
typedef typename OverloadsT::non_void_return_type non_void_return_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
(stubs_type::max_args) <= mpl::size<SigT>::value);
|
||||
typedef typename mpl::if_c<
|
||||
boost::is_same<void, return_type>::value
|
||||
, void_return_type
|
||||
, non_void_return_type
|
||||
>::type stubs_type;
|
||||
|
||||
typedef typename stubs_type::template gen<SigT> gen_type;
|
||||
define_with_defaults_helper<stubs_type::n_funcs-1>::def(
|
||||
name
|
||||
, gen_type()
|
||||
, overloads.keywords()
|
||||
, overloads.call_policies()
|
||||
, name_space
|
||||
, overloads.doc_string());
|
||||
}
|
||||
BOOST_STATIC_ASSERT(
|
||||
(stubs_type::max_args) <= mpl::size<SigT>::value);
|
||||
|
||||
typedef typename stubs_type::template gen<SigT> gen_type;
|
||||
define_with_defaults_helper<stubs_type::n_funcs-1>::def(
|
||||
name
|
||||
, gen_type()
|
||||
, overloads.keywords()
|
||||
, overloads.call_policies()
|
||||
, name_space
|
||||
, overloads.doc_string());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#endif // DEFAULTS_DEF_JDG20020811_HPP
|
||||
|
||||
#else // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
@@ -45,23 +45,19 @@ namespace boost { namespace python { namespace detail {
|
||||
// invoke(...), selecting the appropriate implementation
|
||||
typedef int void_result_to_python;
|
||||
|
||||
// Trait forward declaration.
|
||||
template <class T> struct is_defaulted_virtual_fn;
|
||||
|
||||
// Tag types describing invocation methods
|
||||
struct fn_tag {};
|
||||
struct mem_fn_tag {};
|
||||
template <bool void_return, bool member>
|
||||
struct invoke_tag_ {};
|
||||
|
||||
// A metafunction returning the appropriate tag type for invoking an
|
||||
// object of type T.
|
||||
template <class T>
|
||||
// object of type F with return type R.
|
||||
template <class R, class F>
|
||||
struct invoke_tag
|
||||
: mpl::if_<
|
||||
is_member_function_pointer<T>
|
||||
, mem_fn_tag
|
||||
, fn_tag
|
||||
: invoke_tag_<
|
||||
is_same<R,void>::value
|
||||
, is_member_function_pointer<F>::value
|
||||
>
|
||||
{};
|
||||
{
|
||||
};
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/invoke.hpp>))
|
||||
@@ -75,26 +71,26 @@ struct invoke_tag
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(fn_tag, RC*, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
inline PyObject* invoke(invoke_tag_<false,false>, RC const& rc, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
return RC()(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
|
||||
return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
|
||||
}
|
||||
|
||||
template <class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(fn_tag, void_result_to_python, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(invoke_tag_<true,false>, RC const&, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) );
|
||||
return none();
|
||||
}
|
||||
|
||||
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(mem_fn_tag, RC*, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
inline PyObject* invoke(invoke_tag_<false,true>, RC const& rc, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
return RC()( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );
|
||||
return rc( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );
|
||||
}
|
||||
|
||||
template <class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(mem_fn_tag, void_result_to_python, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(invoke_tag_<true,true>, RC const&, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
(tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT));
|
||||
return none();
|
||||
|
||||
@@ -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_ \
|
||||
{ \
|
||||
};
|
||||
|
||||
|
||||
@@ -21,13 +21,30 @@ namespace boost { namespace python { namespace detail {
|
||||
// F. This version is needed when defining functions with default
|
||||
// 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, Policies const& policies, keyword_range const& kw)
|
||||
object make_keyword_range_function(
|
||||
F f
|
||||
, Policies const& policies
|
||||
, keyword_range const& kw)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f, policies, args_from_python(), detail::get_signature(f), kw, mpl::int_<0>());
|
||||
f, policies, detail::get_signature(f), kw, mpl::int_<0>());
|
||||
}
|
||||
|
||||
template <class F, class Policies, class Signature>
|
||||
object make_keyword_range_function(
|
||||
F f
|
||||
, Policies const& policies
|
||||
, keyword_range const& kw
|
||||
, Signature const& sig)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f, policies, sig, kw, mpl::int_<0>());
|
||||
}
|
||||
// }
|
||||
|
||||
// Builds an '__init__' function which inserts the given Holder type
|
||||
// in a wrapped C++ class instance. ArgList is an MPL type sequence
|
||||
// describing the C++ argument types to be passed to Holder's
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
# ifndef MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
# define MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class S, class FT>
|
||||
struct cast_helper
|
||||
{
|
||||
struct yes_helper
|
||||
{
|
||||
static FT stage3(FT x) { return x; }
|
||||
};
|
||||
|
||||
struct no_helper
|
||||
{
|
||||
template <class T>
|
||||
static T stage3(T x) { return x; }
|
||||
};
|
||||
|
||||
static yes_helper stage2(S*) { return yes_helper(); }
|
||||
static no_helper stage2(void*) { return no_helper(); }
|
||||
};
|
||||
|
||||
struct non_member_function_cast_impl
|
||||
{
|
||||
template <class T>
|
||||
static non_member_function_cast_impl stage1(T) { return non_member_function_cast_impl(); }
|
||||
|
||||
template <class T>
|
||||
static non_member_function_cast_impl stage2(T) { return non_member_function_cast_impl(); }
|
||||
|
||||
template <class T>
|
||||
T stage3(T x) { return x; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct member_function_cast_impl
|
||||
{
|
||||
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
template <class U>
|
||||
static non_member_function_cast_impl stage1(U)
|
||||
{
|
||||
return non_member_function_cast_impl();
|
||||
}
|
||||
# endif
|
||||
|
||||
// Member functions
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/python/detail/member_function_cast.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
};
|
||||
|
||||
template <class T, class SF>
|
||||
struct member_function_cast
|
||||
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
: member_function_cast_impl<T>
|
||||
# else
|
||||
: mpl::if_c<
|
||||
is_member_function_pointer<SF>::value
|
||||
, member_function_cast_impl<T>
|
||||
, non_member_function_cast_impl
|
||||
>::type
|
||||
# endif
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
# endif // MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
// outer over cv-qualifiers
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/member_function_cast.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 2
|
||||
# line BOOST_PP_LINE(__LINE__, member_function_cast.hpp)
|
||||
// inner over arities
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
|
||||
# define P BOOST_PP_ENUM_PARAMS_Z(1, N, A)
|
||||
|
||||
template <
|
||||
class S, class R
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
|
||||
>
|
||||
static cast_helper<S, R (T::*)( P ) Q>
|
||||
stage1(R (S::*)( P ) Q)
|
||||
{
|
||||
return cast_helper<S, R (T::*)( P ) Q>();
|
||||
}
|
||||
|
||||
# undef P
|
||||
# undef N
|
||||
# undef Q
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,12 @@
|
||||
#ifndef NULLARY_FUNCTION_ADAPTOR_DWA2003824_HPP
|
||||
# define NULLARY_FUNCTION_ADAPTOR_DWA2003824_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// nullary_function_adaptor -- a class template which ignores its
|
||||
|
||||
@@ -47,7 +47,8 @@ enum operator_id
|
||||
op_iand,
|
||||
op_ixor,
|
||||
op_ior,
|
||||
op_complex
|
||||
op_complex,
|
||||
op_nonzero
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -9,15 +9,16 @@
|
||||
# ifndef SIGNATURE_DWA20021121_HPP
|
||||
# define SIGNATURE_DWA20021121_HPP
|
||||
|
||||
# include <boost/mpl/at.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/at.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
@@ -33,8 +34,10 @@ template <unsigned> struct signature_arity;
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/signature.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
// A metafunction returning the base class used for signature<class F,
|
||||
// class ConverterGenerators, class CallPolicies, class Sig>.
|
||||
// A metafunction returning the base class used for
|
||||
//
|
||||
// signature<class F, class CallPolicies, class Sig>.
|
||||
//
|
||||
template <class Sig>
|
||||
struct signature_base_select
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace boost { namespace python { namespace detail {
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
template <class R, class T>
|
||||
boost::type<T*>* target(R (T::*)) { return 0; }
|
||||
T& (* target(R (T::*)) )() { return 0; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -39,12 +39,15 @@ boost::type<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()
|
||||
|
||||
template <class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
|
||||
boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)))
|
||||
BOOST_PP_IF(N, A0, void)(* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))) )()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -59,14 +62,17 @@ boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N,
|
||||
# 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()
|
||||
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
|
||||
|
||||
template <class R, class T BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
|
||||
boost::type<T Q*>* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q)
|
||||
T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
//
|
||||
|
||||
@@ -393,13 +393,13 @@ namespace detail
|
||||
template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
|
||||
static void apply(
|
||||
ClassT& cl
|
||||
, CallPoliciesT const& policies
|
||||
, Signature const& args
|
||||
, NArgs
|
||||
, char const* doc
|
||||
, detail::keyword_range const& keywords)
|
||||
, CallPoliciesT const& policies
|
||||
, Signature const& args
|
||||
, NArgs
|
||||
, char const* doc
|
||||
, detail::keyword_range const& keywords)
|
||||
{
|
||||
def_init_aux(cl, args, NArgs(), policies, doc, keywords);
|
||||
detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
# include <boost/python/detail/target.hpp>
|
||||
# include <boost/python/object/iterator.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
@@ -21,14 +25,19 @@ namespace detail
|
||||
// Adds an additional layer of binding to
|
||||
// objects::make_iterator(...), which allows us to pass member
|
||||
// function and member data pointers.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
template <class Target, class Accessor1, class Accessor2, class NextPolicies>
|
||||
inline object make_iterator(
|
||||
Accessor1 get_start, Accessor2 get_finish, boost::type<Target>* target = 0, NextPolicies* = 0)
|
||||
Accessor1 get_start
|
||||
, Accessor2 get_finish
|
||||
, NextPolicies next_policies
|
||||
, Target&(*)()
|
||||
)
|
||||
{
|
||||
return objects::make_iterator_function<NextPolicies,Target>(
|
||||
return objects::make_iterator_function<Target>(
|
||||
boost::protect(boost::bind(get_start, _1))
|
||||
, boost::protect(boost::bind(get_finish, _1))
|
||||
);
|
||||
, boost::protect(boost::bind(get_finish, _1))
|
||||
, next_policies
|
||||
);
|
||||
}
|
||||
|
||||
// Guts of template class iterators<>, below.
|
||||
@@ -73,9 +82,11 @@ struct iterators
|
||||
template <class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish)
|
||||
{
|
||||
return detail::make_iterator<objects::default_iterator_call_policies>(
|
||||
start, finish
|
||||
, detail::target(start));
|
||||
return detail::make_iterator(
|
||||
start, finish
|
||||
, objects::default_iterator_call_policies()
|
||||
, detail::target(start)
|
||||
);
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -83,7 +94,7 @@ object range(Accessor1 start, Accessor2 finish)
|
||||
template <class NextPolicies, class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
{
|
||||
return detail::make_iterator<NextPolicies>(start, finish, detail::target(start));
|
||||
return detail::make_iterator(start, finish, NextPolicies(), detail::target(start));
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -91,8 +102,8 @@ object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator<NextPolicies, target>(start, finish);
|
||||
// typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator(start, finish, NextPolicies(), (Target&(*)())0);
|
||||
}
|
||||
|
||||
// A Python callable object which produces an iterator traversing
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
279
include/boost/python/make_constructor.hpp
Executable file
279
include/boost/python/make_constructor.hpp
Executable file
@@ -0,0 +1,279 @@
|
||||
// Copyright David Abrahams 2001. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef MAKE_CONSTRUCTOR_DWA20011221_HPP
|
||||
# define MAKE_CONSTRUCTOR_DWA20011221_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/object/make_holder.hpp>
|
||||
# include <boost/python/object/pointer_holder.hpp>
|
||||
# include <boost/python/converter/context_result_converter.hpp>
|
||||
|
||||
# include <boost/python/detail/caller.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/int.hpp>
|
||||
# include <boost/mpl/push_front.hpp>
|
||||
# include <boost/mpl/pop_front.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct install_holder : converter::context_result_converter
|
||||
{
|
||||
install_holder(PyObject* args_)
|
||||
: m_self(PyTuple_GetItem(args_, 0)) {}
|
||||
|
||||
PyObject* operator()(T x) const
|
||||
{
|
||||
dispatch(x, is_pointer<T>());
|
||||
return none();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class U>
|
||||
void dispatch(U* x, mpl::true_) const
|
||||
{
|
||||
std::auto_ptr<U> owner(x);
|
||||
dispatch(owner, mpl::false_());
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
void dispatch(Ptr x, mpl::false_) const
|
||||
{
|
||||
typedef typename pointee<Ptr>::type value_type;
|
||||
typedef objects::pointer_holder<Ptr,value_type> holder;
|
||||
typedef objects::instance<holder> instance_t;
|
||||
|
||||
void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
|
||||
try {
|
||||
(new (memory) holder(x))->install(this->m_self);
|
||||
}
|
||||
catch(...) {
|
||||
holder::deallocate(this->m_self, memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* m_self;
|
||||
};
|
||||
|
||||
struct constructor_result_converter
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef install_holder<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class BaseArgs, class Offset>
|
||||
struct offset_args
|
||||
{
|
||||
offset_args(BaseArgs base_) : base(base_) {}
|
||||
BaseArgs base;
|
||||
};
|
||||
|
||||
template <int N, class BaseArgs, class Offset>
|
||||
inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
|
||||
{
|
||||
return get(mpl::int_<(N+Offset::value)>(), args_.base);
|
||||
}
|
||||
|
||||
template <class BaseArgs, class Offset>
|
||||
inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
|
||||
{
|
||||
return arity(args_.base) - Offset::value;
|
||||
}
|
||||
|
||||
template <class BasePolicy_ = default_call_policies>
|
||||
struct constructor_policy : BasePolicy_
|
||||
{
|
||||
constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
|
||||
|
||||
// If the BasePolicy_ supplied a result converter it would be
|
||||
// ignored; issue an error if it's not the default.
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_same<
|
||||
typename BasePolicy_::result_converter
|
||||
, default_result_converter
|
||||
>::value
|
||||
));
|
||||
|
||||
typedef constructor_result_converter result_converter;
|
||||
typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
|
||||
};
|
||||
|
||||
template <class InnerSignature>
|
||||
struct outer_constructor_signature
|
||||
{
|
||||
typedef typename mpl::pop_front<InnerSignature>::type inner_args;
|
||||
typedef typename mpl::push_front<inner_args,object>::type outer_args;
|
||||
typedef typename mpl::push_front<outer_args,void>::type type;
|
||||
};
|
||||
|
||||
// ETI workaround
|
||||
template <>
|
||||
struct outer_constructor_signature<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
//
|
||||
// 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()
|
||||
, CallPolicies const& p // CallPolicies to use in the invocation
|
||||
, Sig const& // An MPL sequence of argument types expected by F
|
||||
)
|
||||
{
|
||||
typedef typename outer_constructor_signature<Sig>::type outer_signature;
|
||||
|
||||
typedef constructor_policy<CallPolicies> inner_policy;
|
||||
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
|
||||
, outer_signature()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// As above, except that it accepts argument keywords. NumKeywords
|
||||
// is used only for a compile-time assertion to make sure the user
|
||||
// doesn't pass more keywords than the function can accept. To
|
||||
// disable all checking, pass mpl::int_<0> for NumKeywords.
|
||||
template <class F, class CallPolicies, class Sig, class NumKeywords>
|
||||
object make_constructor_aux(
|
||||
F f
|
||||
, CallPolicies const& p
|
||||
, Sig const&
|
||||
, detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
|
||||
, NumKeywords // An MPL integral type wrapper: the size of kw
|
||||
)
|
||||
{
|
||||
enum { arity = mpl::size<Sig>::value - 1 };
|
||||
|
||||
typedef typename detail::error::more_keywords_than_function_arguments<
|
||||
NumKeywords::value, arity
|
||||
>::too_many_keywords assertion;
|
||||
|
||||
typedef typename outer_constructor_signature<Sig>::type outer_signature;
|
||||
|
||||
typedef constructor_policy<CallPolicies> inner_policy;
|
||||
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
|
||||
, outer_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_)
|
||||
{
|
||||
return detail::make_constructor_aux(
|
||||
f
|
||||
, policies
|
||||
, detail::get_signature(f)
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Signature>
|
||||
object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
|
||||
{
|
||||
return detail::make_constructor_aux(
|
||||
f
|
||||
, policies
|
||||
, sig
|
||||
);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
// 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_constructor(F f)
|
||||
{
|
||||
return detail::make_constructor_aux(
|
||||
f,default_call_policies(), detail::get_signature(f));
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies>
|
||||
object make_constructor(F f, CallPolicies const& policies)
|
||||
{
|
||||
return detail::make_constructor_aux(
|
||||
f, policies, detail::get_signature(f));
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class KeywordsOrSignature>
|
||||
object make_constructor(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, KeywordsOrSignature const& keywords_or_signature)
|
||||
{
|
||||
typedef typename
|
||||
detail::is_reference_to_keywords<KeywordsOrSignature&>::type
|
||||
is_kw;
|
||||
|
||||
return detail::make_constructor_dispatch(
|
||||
f
|
||||
, policies
|
||||
, keywords_or_signature
|
||||
, is_kw()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Keywords, class Signature>
|
||||
object make_constructor(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, Keywords const& kw
|
||||
, Signature const& sig
|
||||
)
|
||||
{
|
||||
return detail::make_constructor_aux(
|
||||
f
|
||||
, policies
|
||||
, sig
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
}
|
||||
// }
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // MAKE_CONSTRUCTOR_DWA20011221_HPP
|
||||
@@ -9,7 +9,7 @@
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/detail/caller.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
@@ -26,17 +26,16 @@ namespace detail
|
||||
// These helper functions for make_function (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 ConverterGenerators and Sig arguments are used.
|
||||
template <class F, class CallPolicies, class ConverterGenerators, class Sig>
|
||||
// the Sig arguments is used.
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
object make_function_aux(
|
||||
F f // An object that can be invoked by detail::invoke()
|
||||
, CallPolicies const& p // CallPolicies to use in the invocation
|
||||
, ConverterGenerators const& // An MPL iterator over a sequence of arg_from_python generators
|
||||
, Sig const& // An MPL sequence of argument types expected by F
|
||||
)
|
||||
{
|
||||
return objects::function_object(
|
||||
detail::caller<F,ConverterGenerators,CallPolicies,Sig>(f, p)
|
||||
detail::caller<F,CallPolicies,Sig>(f, p)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,11 +43,10 @@ namespace detail
|
||||
// is used only for a compile-time assertion to make sure the user
|
||||
// doesn't pass more keywords than the function can accept. To
|
||||
// disable all checking, pass mpl::int_<0> for NumKeywords.
|
||||
template <class F, class CallPolicies, class ConverterGenerators, class Sig, class NumKeywords>
|
||||
template <class F, class CallPolicies, class Sig, class NumKeywords>
|
||||
object make_function_aux(
|
||||
F f
|
||||
, CallPolicies const& p
|
||||
, ConverterGenerators const&
|
||||
, Sig const&
|
||||
, detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
|
||||
, NumKeywords // An MPL integral type wrapper: the size of kw
|
||||
@@ -61,42 +59,94 @@ namespace detail
|
||||
>::too_many_keywords assertion;
|
||||
|
||||
return objects::function_object(
|
||||
detail::caller<F,ConverterGenerators,CallPolicies,Sig>(f, p)
|
||||
detail::caller<F,CallPolicies,Sig>(f, p)
|
||||
, kw);
|
||||
}
|
||||
}
|
||||
|
||||
// make_function --
|
||||
// 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_)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
, policies
|
||||
, detail::get_signature(f)
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Signature>
|
||||
object make_function_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
, policies
|
||||
, sig
|
||||
);
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies,
|
||||
// Keywords, and/or Signature.
|
||||
//
|
||||
// These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies and
|
||||
// Keywords.
|
||||
// @group {
|
||||
template <class F>
|
||||
object make_function(F f)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f,default_call_policies(),detail::args_from_python(), detail::get_signature(f));
|
||||
f,default_call_policies(), detail::get_signature(f));
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies>
|
||||
object make_function(F f, CallPolicies const& policies)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f,policies,detail::args_from_python(), detail::get_signature(f));
|
||||
f, policies, detail::get_signature(f));
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Keywords>
|
||||
object make_function(F f, CallPolicies const& policies, Keywords const& keywords)
|
||||
template <class F, class CallPolicies, class KeywordsOrSignature>
|
||||
object make_function(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, KeywordsOrSignature const& keywords_or_signature)
|
||||
{
|
||||
typedef typename
|
||||
detail::is_reference_to_keywords<KeywordsOrSignature&>::type
|
||||
is_kw;
|
||||
|
||||
return detail::make_function_dispatch(
|
||||
f
|
||||
, policies
|
||||
, keywords_or_signature
|
||||
, is_kw()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Keywords, class Signature>
|
||||
object make_function(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, Keywords const& kw
|
||||
, Signature const& sig
|
||||
)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
f
|
||||
, policies
|
||||
, detail::args_from_python()
|
||||
, detail::get_signature(f)
|
||||
, keywords.range()
|
||||
, sig
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
);
|
||||
}
|
||||
// }
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -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>();
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/object/py_function.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -26,7 +25,7 @@ inline handle<> function_handle(F const& f, Signature)
|
||||
|
||||
return objects::function_handle_impl(
|
||||
python::detail::caller<
|
||||
F,python::detail::args_from_python,default_call_policies,Signature
|
||||
F,default_call_policies,Signature
|
||||
>(
|
||||
f, default_call_policies()
|
||||
)
|
||||
|
||||
@@ -6,20 +6,26 @@
|
||||
#ifndef ITERATOR_DWA2002510_HPP
|
||||
# define ITERATOR_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/object/iterator_core.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/object/class_detail.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/return_by_value.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
|
||||
# include <boost/python/object/iterator_core.hpp>
|
||||
# include <boost/python/object/class_detail.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
|
||||
@@ -40,6 +46,62 @@ struct iterator_range
|
||||
{
|
||||
iterator_range(object sequence, Iterator start, Iterator finish);
|
||||
|
||||
typedef boost::detail::iterator_traits<Iterator> traits_t;
|
||||
|
||||
struct next
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_reference<
|
||||
typename traits_t::reference
|
||||
>
|
||||
, typename traits_t::reference
|
||||
, typename traits_t::value_type
|
||||
>::type result_type;
|
||||
|
||||
result_type
|
||||
operator()(iterator_range<NextPolicies,Iterator>& self)
|
||||
{
|
||||
if (self.m_start == self.m_finish)
|
||||
stop_iteration_error();
|
||||
return *self.m_start++;
|
||||
}
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
// CWPro8 has a codegen problem when this is an empty class
|
||||
int garbage;
|
||||
# endif
|
||||
};
|
||||
|
||||
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// for compilers which can't deduce the value_type of pointers, we
|
||||
// have a special implementation of next. This takes advantage of
|
||||
// the fact that T* results are treated like T& results by
|
||||
// Boost.Python's function wrappers.
|
||||
struct next_ptr
|
||||
{
|
||||
typedef Iterator result_type;
|
||||
|
||||
result_type
|
||||
operator()(iterator_range<NextPolicies,Iterator>& self)
|
||||
{
|
||||
if (self.m_start == self.m_finish)
|
||||
stop_iteration_error();
|
||||
return self.m_start++;
|
||||
}
|
||||
};
|
||||
|
||||
typedef mpl::if_<
|
||||
is_same<
|
||||
boost::detail::please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<Iterator>
|
||||
, typename traits_t::value_type
|
||||
>
|
||||
, next_ptr
|
||||
, next
|
||||
>::type next_fn;
|
||||
# else
|
||||
typedef next next_fn;
|
||||
# endif
|
||||
|
||||
object m_sequence; // Keeps the sequence alive while iterating.
|
||||
Iterator m_start;
|
||||
Iterator m_finish;
|
||||
@@ -47,62 +109,6 @@ struct iterator_range
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Guts of the iterator's next() function. We can't just wrap an
|
||||
// ordinary function because we don't neccessarily know the result
|
||||
// type of dereferencing the iterator. This also saves us from
|
||||
// throwing C++ exceptions to indicate end-of-sequence.
|
||||
template <class Iterator, class Policies>
|
||||
struct iterator_next
|
||||
{
|
||||
static PyObject* execute(PyObject* args_, PyObject* kw, Policies const& policies)
|
||||
{
|
||||
typedef iterator_range<Policies,Iterator> range_;
|
||||
|
||||
PyObject* py_self = PyTuple_GET_ITEM(args_, 0);
|
||||
arg_from_python<range_*> c0(py_self);
|
||||
range_* self = c0(py_self);
|
||||
|
||||
// Done iterating?
|
||||
if (self->m_start == self->m_finish)
|
||||
{
|
||||
objects::set_stop_iteration_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// note: precall happens before we can check for the result
|
||||
// converter in this case, to ensure it happens before the
|
||||
// iterator is dereferenced. However, the arity is 1 so
|
||||
// there's not much risk that this will amount to anything.
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = iterator_next::convert_result(*self->m_start);
|
||||
++self->m_start;
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
private:
|
||||
// Convert the result of dereferencing the iterator. Dispatched
|
||||
// here because we can't neccessarily get the value_type of the
|
||||
// iterator without PTS. This way, we deduce the value type by
|
||||
// dereferencing.
|
||||
template <class ValueType>
|
||||
static PyObject* convert_result(ValueType& x)
|
||||
{
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typename mpl::apply1<result_converter,ValueType&>::type cr;
|
||||
|
||||
return cr(x);
|
||||
}
|
||||
template <class ValueType>
|
||||
static PyObject* convert_result(ValueType const& x)
|
||||
{
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typename mpl::apply1<result_converter,ValueType const&>::type cr;
|
||||
|
||||
return cr(x);
|
||||
}
|
||||
};
|
||||
|
||||
// Get a Python class which contains the given iterator and
|
||||
// policies, creating it if neccessary. Requires: NextPolicies is
|
||||
// default-constructible.
|
||||
@@ -118,93 +124,90 @@ namespace detail
|
||||
if (class_obj.get() != 0)
|
||||
return object(class_obj);
|
||||
|
||||
// Make a callable object which can be used as the iterator's next() function.
|
||||
object next_function =
|
||||
objects::function_object(
|
||||
py_function(
|
||||
bind(&detail::iterator_next<Iterator,NextPolicies>::execute, _1, _2, policies)
|
||||
, mpl::vector2<
|
||||
# if defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
object
|
||||
# else
|
||||
typename boost::detail::iterator_traits<Iterator>::value_type
|
||||
# endif
|
||||
, Iterator
|
||||
>()
|
||||
)
|
||||
);
|
||||
|
||||
typedef typename range_::next_fn next_fn;
|
||||
typedef typename next_fn::result_type result_type;
|
||||
|
||||
return class_<range_>(name, no_init)
|
||||
.def("__iter__", identity_function())
|
||||
.setattr("next", next_function)
|
||||
;
|
||||
.def(
|
||||
"next"
|
||||
, make_function(
|
||||
next_fn()
|
||||
, policies
|
||||
, mpl::vector2<result_type,range_&>()
|
||||
));
|
||||
}
|
||||
|
||||
// This class template acts as a generator for an ordinary function
|
||||
// which builds a Python iterator.
|
||||
template <class Target, class Iterator
|
||||
, class Accessor1, class Accessor2
|
||||
, class NextPolicies
|
||||
>
|
||||
struct make_iterator_help
|
||||
// A function object which builds an iterator_range.
|
||||
template <
|
||||
class Target
|
||||
, class Iterator
|
||||
, class Accessor1
|
||||
, class Accessor2
|
||||
, class NextPolicies
|
||||
>
|
||||
struct py_iter_
|
||||
{
|
||||
py_iter_(Accessor1 const& get_start, Accessor2 const& get_finish)
|
||||
: m_get_start(get_start)
|
||||
, m_get_finish(get_finish)
|
||||
{}
|
||||
|
||||
// Extract an object x of the Target type from the first Python
|
||||
// argument, and invoke get_start(x)/get_finish(x) to produce
|
||||
// iterators, which are used to construct a new iterator_range<>
|
||||
// object that gets wrapped into a Python iterator.
|
||||
static PyObject* create(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, PyObject* args_, PyObject* /*kw*/)
|
||||
iterator_range<NextPolicies,Iterator>
|
||||
operator()(back_reference<Target&> x) const
|
||||
{
|
||||
// Make sure the Python class is instantiated.
|
||||
detail::demand_iterator_class("iterator", (Iterator*)0, NextPolicies());
|
||||
|
||||
to_python_value<iterator_range<NextPolicies,Iterator> > cr;
|
||||
|
||||
// Extract x from the first argument
|
||||
PyObject* arg0 = PyTuple_GET_ITEM(args_, 0);
|
||||
arg_from_python<Target> c0(arg0);
|
||||
if (!c0.convertible()) return 0;
|
||||
typename arg_from_python<Target>::result_type x = c0(arg0);
|
||||
|
||||
// Build and convert the iterator_range<>.
|
||||
return cr(
|
||||
iterator_range<NextPolicies,Iterator>(
|
||||
object((python::detail::borrowed_reference)arg0)
|
||||
, get_start(x), get_finish(x)));
|
||||
|
||||
return iterator_range<NextPolicies,Iterator>(
|
||||
x.source()
|
||||
, m_get_start(x.get())
|
||||
, m_get_finish(x.get())
|
||||
);
|
||||
}
|
||||
private:
|
||||
Accessor1 m_get_start;
|
||||
Accessor2 m_get_finish;
|
||||
};
|
||||
|
||||
template <class NextPolicies, class Target, class Iterator, class Accessor1, class Accessor2>
|
||||
template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, Iterator const& (*)()
|
||||
, boost::type<Target>*
|
||||
, NextPolicies*
|
||||
, int
|
||||
)
|
||||
{
|
||||
return
|
||||
objects::function_object(
|
||||
py_function(
|
||||
boost::bind(
|
||||
&make_iterator_help<
|
||||
Target,Iterator,Accessor1,Accessor2,NextPolicies
|
||||
>::create
|
||||
, get_start, get_finish, _1, _2)
|
||||
, mpl::vector2<object, Target>()
|
||||
)
|
||||
);
|
||||
return make_function(
|
||||
py_iter_<Target,Iterator,Accessor1,Accessor2,NextPolicies>(get_start, get_finish)
|
||||
, default_call_policies()
|
||||
, mpl::vector2<iterator_range<NextPolicies,Iterator>, back_reference<Target&> >()
|
||||
);
|
||||
}
|
||||
|
||||
template <class NextPolicies, class Target, class Iterator, class Accessor1, class Accessor2>
|
||||
template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish, Iterator& (*)(), boost::type<Target>*, NextPolicies*, ...)
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, Iterator& (*)()
|
||||
, boost::type<Target>*
|
||||
, ...)
|
||||
{
|
||||
return make_iterator_function(
|
||||
get_start, get_finish, (Iterator const&(*)())0
|
||||
, (boost::type<Target>*)0, (NextPolicies*)0, 0);
|
||||
get_start
|
||||
, get_finish
|
||||
, next_policies
|
||||
, (Iterator const&(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, 0
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -215,22 +218,26 @@ namespace detail
|
||||
// (where x is an instance of Target) to produce begin and end
|
||||
// iterators for the range, and an instance of NextPolicies is used as
|
||||
// CallPolicies for the Python iterator's next() function.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
template <class Target, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, boost::type<Target>* = 0, NextPolicies* = 0)
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, boost::type<Target>* = 0
|
||||
)
|
||||
{
|
||||
typedef typename Accessor1::result_type iterator;
|
||||
typedef typename add_const<iterator>::type iterator_const;
|
||||
typedef typename add_reference<iterator_const>::type iterator_cref;
|
||||
|
||||
return detail::make_iterator_function(
|
||||
get_start, get_finish
|
||||
, (iterator_cref(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, (NextPolicies*)0
|
||||
, 0
|
||||
);
|
||||
get_start
|
||||
, get_finish
|
||||
, next_policies
|
||||
, (iterator_cref(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, 0
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
BOOST_PYTHON_DECL object const& identity_function();
|
||||
BOOST_PYTHON_DECL void set_stop_iteration_error();
|
||||
BOOST_PYTHON_DECL void stop_iteration_error();
|
||||
|
||||
}}} // namespace boost::python::object
|
||||
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -334,6 +334,7 @@ BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
# include <boost/python/def_visitor.hpp>
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/mpl/push_front.hpp>
|
||||
# include <boost/mpl/pop_front.hpp>
|
||||
|
||||
@@ -19,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
|
||||
@@ -44,9 +43,9 @@ namespace detail
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// Given an MPL sequence representing a signature, returns a new MPL
|
||||
// sequence whose return type is replaced by void, and whose first
|
||||
// argument is replaced by C&.
|
||||
// Given an MPL sequence representing a member function [object]
|
||||
// signature, returns a new MPL sequence whose return type is
|
||||
// replaced by void, and whose first argument is replaced by C&.
|
||||
template <class C, class S>
|
||||
typename replace_front2<S,void,C&>::type
|
||||
error_signature(S BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(C))
|
||||
@@ -56,7 +55,7 @@ namespace detail
|
||||
}
|
||||
|
||||
//
|
||||
// } Helpers for pure_virtual_visitor
|
||||
// }
|
||||
//
|
||||
|
||||
//
|
||||
@@ -72,7 +71,9 @@ namespace detail
|
||||
: m_pmf(pmf)
|
||||
{}
|
||||
|
||||
#if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
|
||||
private:
|
||||
#endif
|
||||
friend class def_visitor_access;
|
||||
|
||||
template <class C_, class Options>
|
||||
@@ -95,10 +96,9 @@ namespace detail
|
||||
// Add the default implementation which raises the exception
|
||||
c.def(
|
||||
name
|
||||
, detail::make_function_aux(
|
||||
, make_function(
|
||||
detail::nullary_function_adaptor<void(*)()>(pure_virtual_called)
|
||||
, default_call_policies()
|
||||
, args_from_python()
|
||||
, detail::error_signature<held_t>(detail::get_signature(m_pmf))
|
||||
)
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user